C言語関係掲示板

過去ログ

No.54. 値を導き出すための計算式を・・・


どうも、ご無沙汰しておりました。MASAです。
さて、早速ですが、解からその解を求めるための式を出したいのです。
例えば、解が"10"であった場合、"式=1+2+3+4"というように求めたいわけです。
(式は解さえ合っていれば、"式=7-5*2+0+3-1-4+6+9"となっても構いません。)

私の考えている条件としては、
1.0〜9までの数字をそれぞれ1度ずつ使用(どんな解でも全部1度ずつ使用したい)
2.加算だけでなく乗除も使用(出来れば)
です。

今、"2"の部分で詰まっている状態です。(考え方がどうにも分からないです)
どなたか、アドバイス御願いできないでしょうか?

それでわ、失礼します。


こんばんは、ともじです。毎日暑いですね。

さて、ご提示の処理ですが、難しいですね。
以下のようにやってみましたが、あまりよい例ではないかもしれません。

> 1.0〜9までの数字をそれぞれ1度ずつ使用(どんな解でも全部1度ずつ使用したい)
> 2.加算だけでなく乗除も使用(出来れば)

一応、この条件は満たしていますが、0〜9の数字を使った時点で、最後につじつまを
合わせて、解よりも計算結果が大きければその分を減算、解よりも計算結果が
小さければその分を加算、というように計算を行っています。

なお、乗算は優先順位を考えるのが面倒だったので、最初にまとめてやってしまって
います。
頭の体操になりますので、他の方も挑戦してみてください。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int endck(int num[][2]);

int main(void)
{
        int     num[10][2] = {{0,0},{1,0},{2,0},{3,0},{4,0},
                              {5,0},{6,0},{7,0},{8,0},{9,0}};
        int     i,j,n,kai;
        long    kekka=0;
        time_t  t;

         /* 乱数系列の変更 */
         srand((unsigned) time(&t));

        printf("解=");
        scanf("%d",&kai);

        /* 初期値の決定 */
        i = rand()%10;
        kekka = num[i][0];
        printf("%d",num[i][0]);
        num[i][1]++;

        /* 先に乗算 */
        n = rand()%(kai/10+1)+1;
        for (j=0; j<n; j++) {
                i = rand()%10;
                kekka *= num[i][0];
                printf("*%d",num[i][0]);
                num[i][1]++;
        }
        
        /* 未使用データがなくなるまで処理 */
        while (!endck(num)) {
                i = rand()%10;
                if (num[i][1] > 0) continue;
                /* 加算と減算の選択 */
                if ( rand()%2 ) {
                        kekka += num[i][0];
                        printf("+%d",num[i][0]);
                }
                else {
                        kekka -= num[i][0];
                        printf("-%d",num[i][0]);
                }
                /* 使用済み */
                num[i][1]++;
        }
        if ( kekka > kai ) {
                printf("-%d",kekka-kai);
                kekka -= (kekka-kai);
        }
        else {
                printf("+%d",kai-kekka);
                kekka += (kai-kekka);
        }
        printf("=%d\n",kekka);

        return(0);
}

/* 未使用データチェック処理 */
int endck(int   num[][2])
{
        int     i;

        for (i=0; i<10; i++) {
                if (num[i][1] == 0) {
                        /* 未使用データあり返却 */
                        return(0);
                }
        }
        /* 未使用データなし返却 */
        return(1);
}


MASAです。
ともじさん、おはようございます。

>こんばんは、ともじです。毎日暑いですね。
ホントに毎日暑いですね。
今日もまた暑くなりそうです。
毎日30度を超える暑さが続くと水不足が心配ですけど。

素早いレス有り難う御座います。
ともじさんが難しいおっしゃるのでは、私には最初から無理だったのかも(笑)
自分で問題(内容)考えているのですが、自分のスキルに合っていない問題ばかりを考えてしまって・・・。
さて、プログラムの中で少し分からないところがあるので、教えていただけないでしょうか?

<PRE>
/* 先に乗算 */
n = rand()%(kai/10+1)+1;
for (j=0; j<n; j++) {
i = rand()%10;
kekka *= num[i][0];
printf("*%d",num[i][0]);
num[i][1]++;
}
</PRE>

上記の"n = rand()%(kai/10+1)+1"の部分ですけれども、ここはどういった処理をしているのでしょうか?
しばらく考えてはみたのですが閃きません。
他は、何とか大丈夫ですので御願いします。


>今日もまた暑くなりそうです。
>毎日30度を超える暑さが続くと水不足が心配ですけど。

実家が川崎にありますが、妹が取水制限は必須だと言っていました。
こちらの方は、毎晩のように夕立があり、とりあえず水不足は心配なさそうです。

>さて、プログラムの中で少し分からないところがあるので、教えていただけないでしょうか?
/* 先に乗算 */
        n = rand()%(kai/10+1)+1;
        for (j=0; j<n; j++) {
                i = rand()%10;
                kekka *= num[i][0];
                printf("*%d",num[i][0]);
                num[i][1]++;
        }


>上記の"n = rand()%(kai/10+1)+1"の部分ですけれども、ここはどういった処理をしているのでしょうか?

これは、何でも良かったのですが、単に乗算の回数を決めているだけです。
固定だと面白くないので、ちょっと細工してみました。

きっと、もっと効率の良いアルゴリズムがあるのでしょうが、考え付きません
でした。もっと、参加者の多い掲示板やMLだと、面白い解法が寄せられるかも
知れません。何か、面白いやり方を見つけたら、また教えてください。


おはようございます、MASAです。

>>上記の"n = rand()%(kai/10+1)+1"の部分ですけれども、ここはどういった処理をしているのでしょうか?
>
>これは、何でも良かったのですが、単に乗算の回数を決めているだけです。
>固定だと面白くないので、ちょっと細工してみました。
>
>きっと、もっと効率の良いアルゴリズムがあるのでしょうが、考え付きません
>でした。もっと、参加者の多い掲示板やMLだと、面白い解法が寄せられるかも
>知れません。何か、面白いやり方を見つけたら、また教えてください。

なるほど、回数を決めているだけですか。
回答有り難う御座いました。
ともじさんのプログラムを参考にして、自分でも考えてみたいと思います。
出来るかどうかは分かりませんけど・・・。

それでは、暑い日が続きますが、夏ばてなどをおこしません様にお体に気を付けてください。
失礼します。

戻る


「初心者のためのポイント学習C言語」 Last modified:2001.10.7
Copyright(c) 2000-2002 TOMOJI All Rights Reserved