プロが教える店舗&オフィスのセキュリティ対策術

C言語のプログラミングの問題です。
1桁の整数4つをキーボードから入力して、四則演算で10になる式をすべて出力するという問題で、演算子の優先順位ありで、括弧は使わないとし、数字は入れ替え可能です。
また、プログラムはint型の変数を用いるというものです。
とりあえずは数字入れ替えなしで、次のような力技でソースコードを作ってみたのですが、数字の入れ替えまで考えるとあまりに力技すぎるようなだらだらとしたプログラムになってしまいます。。。
数字の入れ替え可能としてもっと簡単なプログラムを作るにはどのようなソースコードになるのでしょうか。

以下ソースコードです。

#include<stdio.h>
#include<math.h>

int main(void) {

int a, b, c, d = 0;

printf("一桁の整数4つを入力してください。\n");
scanf_s("%d %d %d %d", &a, &b, &c, &d);

if (a + b - c * d == 10)
printf("%d+%d-%d*%d\n", a, b, c, d);
else if (a + b - c / d == 10)
printf("%d+%d-%d/%d\n", a, b, c, d);
else if (a + b * c - d == 10)
printf("%d+%d*%d-%d\n", a, b, c, d);
else if (a + b * c / d == 10)
printf("%d+%d*%d/%d\n", a, b, c, d);
else if (a + b / c - d == 10)
printf("%d+%d/%d-%d\n", a, b, c, d);
else if (a + b / c * d == 10)
printf("%d+%d/%d*%d\n", a, b, c, d);
else if (a - b + c * d == 10)
printf("%d-%d+%d*%d\n", a, b, c, d);
else if (a - b + c / d == 10)
printf("%d-%d+%d/%d\n", a, b, c, d);
else if (a - b * c + d == 10)
printf("%d-%d*%d+%d\n", a, b, c, d);
else if (a - b * c / d == 10)
printf("%d-%d*%d/%d\n", a, b, c, d);
else if (a - b / c + d == 10)
printf("%d-%d/%d+%d\n", a, b, c, d);
else if (a - b / c * d == 10)
printf("%d-%d/%d*%d\n", a, b, c, d);
else if (a * b + c - d == 10)
printf("%d*%d+%d-%d\n", a, b, c, d);
else if (a * b + c / d == 10)
printf("%d*%d+%d/%d\n", a, b, c, d);
else if (a * b - c + d == 10)
printf("%d*%d-%d+%d\n", a, b, c, d);
else if (a * b - c / d == 10)
printf("%d*%d-%d/%d\n", a, b, c, d);
else if (a * b / c + d == 10)
printf("%d*%d/%d+%d\n", a, b, c, d);
else if (a * b / c - d == 10)
printf("%d*%d/%d-%d\n", a, b, c, d);
else if (a / b + c - d == 10)
printf("%d/%d+%d-%d\n", a, b, c, d);
else if (a / b + c * d == 10)
printf("%d/%d+%d*%d\n", a, b, c, d);
else if (a / b - c + d == 10)
printf("%d/%d-%d+%d\n", a, b, c, d);
else if (a / b - c * d == 10)
printf("%d/%d-%d*%d\n", a, b, c, d);
else if (a / b * c + d == 10)
printf("%d/%d*%d+%d\n", a, b, c, d);
else if (a / b * c - d == 10)
printf("%d/%d*%d-%d\n", a, b, c, d);
else {
printf("10になる組み合わせはありません。");
}

return 0;

}

質問者からの補足コメント

  • 判定部分を関数にするとはどういうことでしょうか。swap関数を用いようかと思うのですが、2つの変数の値の交換はわかるのですが、4つの変数の値を交換する方法がわかりません、、、
    初歩的なことですみません、、、

    No.1の回答に寄せられた補足コメントです。 補足日時:2017/05/15 01:29
  • sub関数の呼び出しはどの部分で行えばいいのでしょうか?

    No.2の回答に寄せられた補足コメントです。 補足日時:2017/05/15 01:44
  • たびたびすみません^^;
    今回のプログラムでは、int型の変数のみの使用可という制約があり、浮動小数点に変換できないため、おっしゃるように、1/2が0扱いになるなどのように小数点以下が切り捨てられてしまい、計算が正確でなくなってしまいます、、、
    この制約がある限り、力技ではできないんですかね。。。

    No.3の回答に寄せられた補足コメントです。 補足日時:2017/05/15 02:30
  • int型のみだと、計算上で1/2(=0.5)や3/4(=0.75)などが、小数点以下切り捨てにより0になってしまうので、商に0.5をさらに足すことで、小数点以下切り捨てでも四捨五入と同じ条件になるようにました。
    例えば、a + (b * c / d + 0.5) のような感じです。
    ただ、a * b - (c / d + 0.5) など、商を除算する場合、0.5余分に引いてしまうため、
    例えば3 * 4 - (8 / 5 + 0.5) の場合、12 - 2.1 = 9.9 ≒ 9となってしまいます。
    故にa * b - (c / d + 0.5) + 0.5 と、0.5を後で加えることで、
    上の例の場合、3 * 4 - (8 / 5 + 0.5) + 0.5 = (12 - 2.1) + 0.5 = 10.4 ≒ 10 とでき、
    この問題点を解消しました。

    No.6の回答に寄せられた補足コメントです。 補足日時:2017/05/16 00:10
  • 1) 同じ値は複数あってもよいとしています。
    2) 演算子は重複使用不可です。
    3) 計算結果は算術的に10になることです。
    3)に関しては、No.6さんに対する補足コメントにて、自分なりにソースコードに修正を加えた説明を述べているので、そちらも目を通して下さいますようお願いします。

    No.7の回答に寄せられた補足コメントです。 補足日時:2017/05/16 00:21
  • 算術的に10.0以上かつ11未満でOKということです。

    No.9の回答に寄せられた補足コメントです。 補足日時:2017/05/16 01:05
  • (小数点以下が無視される)int型の変数のみを使ったプログラムという指定があったので、私が算術的に10.0以上かつ11未満という条件だと思って解きました。

    No.11の回答に寄せられた補足コメントです。 補足日時:2017/05/21 08:39

A 回答 (15件中11~15件)

>int型の変数のみの使用可



なーんと。

割り算よりも乗算の方が優先。が入ると計算の順番を考えなきゃいけないくなる。
もちろん乗除算は加減算より優先。

そうなってくると「構文解析」というのは大げさだけど、計算順序を並べ替える、または乗除算のところを一つの固まり、加減算はそれぞれ一つの固まりみたいな・・・、

あ、違う。

たとえば上のプログラム、

else if (a / b * c + d == 10)
printf("%d/%d*%d+%d\n", a, b, c, d);

のところは、

else if (a * c / b + d == 10) // 元は a / b * c + d なの!
printf("%d/%d*%d+%d\n", a, b, c, d);

として、printf はそのままで、都合の悪い計算のところだけ自分でエディットしてしまえ、でいいんじゃないかしらと。
ならば行数も増えないし。

もちろん、後で見た時に意味不明になるので、コメントを入れるのは絶対では無いにしても必要かと。

どーでしょーか。
なんだかオイラの書くプログラムみたいになってきましたがw
    • good
    • 0

浮動小数がだめなら有理数にすればいいじゃないか.

    • good
    • 0

>sub関数の呼び出しはどの部分で行えばいいのでしょうか?



scanf の直後でいいのでは。

sub( a, b, c, d );
sub( b, a, c, d );
  :
という具合。
この回答への補足あり
    • good
    • 0
この回答へのお礼

あ、わかりました。関数の勉強不足でした。。。^^;
おかげさまで解決しました。ありがとうございます!

お礼日時:2017/05/15 02:17

お疲れ様です、貧乏じーさんプログラマです。



いや、こういう力技は私は結構好きですよ。

その if の塊を sub( a, b, c, d ) {...}という関数にして
呼び出しを sub( a, b, c, d ); sub( b, a, c, d ); ...
にして4x3x2x1=24行コピペで追加すれば、じゃーん。
「なんか文句ありますか」。

だって、開発の仕事で、考えたり試したりする時間がなければ普通にこうしちゃうし。

ただ、「一番行数が短かった者が優勝!」という条件付きならば・・・。
  :
「ハノイの塔」よろしく、リカーシブコールが使えないかと考えてみますか・・・。
ただ、デバッグで頭が破裂するので嫌ですw

あ、ちなみに a ○ b ○ c ○ d ということは、4x4x4 で 64 通り書かないと正解にならないと思います。
たとえば a + b + c + d 。あれ?同じ符号は使うなって?
もちろん abcd に何を入れても 10 にはならない場合も含めて。

あ、あ、あ、あと、計算するときは浮動小数点に変換してからでないと、整数で割り算すると小数点以下が切られてしまいます。
4 / 3 * 3 は 4 とならない可能性が。
そか、 sub() の引数を浮動小数点で受ければいいのか。

参考にならなければ通報しちゃってくださいw
この回答への補足あり
    • good
    • 0

「関数」の作り方はわかりますか?



判定部分を関数にして、引数で4つの変数を入れ替えれば、このifは一つで済みます。

ただ、現在は「四則演算で10になる式をすべて出力する」という条件には合ってません。
この回答への補足あり
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!