From g97p0352@mn.waseda.ac.jp Fri May 14 05:31:01 1999 Received: from wise13.mn.waseda.ac.jp (wise13.mn.waseda.ac.jp [133.9.4.145]) by newton.kashi.info.waseda.ac.jp (8.8.8/3.7W) with ESMTP id FAA03107 for ; Fri, 14 May 1999 05:30:59 +0900 (JST) Received: from wise20.mn.waseda.ac.jp (wise20.mn.waseda.ac.jp [133.9.4.141]) by wise13.mn.waseda.ac.jp (8.9.1a/3.7W-19980811) with ESMTP id FAA25011 for ; Fri, 14 May 1999 05:20:04 +0900 (JST) Received: from wise19.mn.waseda.ac.jp (wise19.mn.waseda.ac.jp [133.9.4.137]) by wise20.mn.waseda.ac.jp (8.9.1+3.0W/3.7W-19981111) with ESMTP id FAA17556 for ; Fri, 14 May 1999 05:20:04 +0900 (JST) Received: from Kei (pc045113.tokyo.ppp.waseda.ac.jp [133.9.45.113]) by wise19.mn.waseda.ac.jp (8.9.1a/3.7W-19980811) with SMTP id FAA07573 for ; Fri, 14 May 1999 05:20:03 +0900 (JST) Message-ID: <000901be9d7d$25e9ba60$0200a8c0@Kei> From: "Kei Kudo" To: Subject: [JSJ]Report Date: Fri, 14 May 1999 05:13:58 +0900 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-2022-jp" Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 5.00.2014.211 X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2014.211 Status: OR 工藤 径 g97p0352 情報システム実験A課題 問題: 4つの数字から四則演算を用いて10になるようなものを求めるプログラムを作る。 1.問題を解くプログラムのアルゴリズム  例えば4つの数字が9999のとき、人間が解くならば「明らかに9+9+9+9や9-9-9-9は 10にならないだろう」ということがわかるのである程度方針を立てて(?)解こうとし ますが、実際そんな所まで考慮して解いていくプログラムを作ることは僕にはできな いので、演算子と数字の順序を総当りで当てはめていって、それぞれの場合で計算し 答えが10ならばその式を出力する、という方法で解くようにしました。 2.総当りでいくと何通りの式が出来上がるか?  式をポーランド記法で表せば、 @@@NNNN @@NN@NN @@N@NNN (それぞれの@は演算子、Nは数字を表す。) 上の3通りで全ての式が表せます。 それぞれの@には4通りの演算子が入るので 4^3=64通り また4つのNの並び方は 4!=24通り 式が3通りあるので合計で 64*24*3=4608通り ということになります。ただしこの中には同じ式が含まれます。(演算子が+-のみの ときなど) 3.プログラムの解説  かなり汚いプログラムになってしまいましたが、一応工夫した点として、 ・for文を使えるようにするために演算子を数で表すようにした。(0,1,2,3が +,-,*,/)  演算子を数で表したままでは計算できないので関数calを作った。 ・例えば4つの数字が1199のとき、(1+1/9)*9=10だが、  分数計算はできないので4つの数字をdouble型の変数に入れ、  計算結果が9.9から10.1の範囲であれば10であるとみなすようにした。 また、ソースの中で理解しづらいと思われるところの解説として、 ・変数i,j,k,lは、前述のポーランド記法で4つのNの並び方を  すべて網羅するために使っています。  4つの数字は配列nに入っていて、n[i]のように参照します。  1つの式で同じ数字を使ってはまずいのでwhileで同じものを  はじくようにしています。  if(i<4)となっているのは直前のwhileでi=4となったときn[4]を  参照しないようにするためです。  また、変数a,b,cは演算子の当てはめ方を全て網羅するために  使っています。 ・計算結果を変数ansに代入していますが、式が例えば(1-1)/(9-9)のとき、  ansにはNULLが代入され、(9.91199 *+1/199=10 *+1/199=10 *+/1919=10 *+/1919=10 *+1/199=10 *+1/199=10 *+/1919=10 *+/1919=10 (2) >3573 *-*3375=10 *-*3375=10 5.プログラムソース #include #include file://n(a)(b)を計算する double cal(double a,double b,int n) { switch(n) { case 0: return a+b; case 1: return a-b; case 2: return a*b; case 3: return a/b; default: printf("error in cal\n"); exit(0); } } file://0,1,2,3を+,-,*,/に変換する char itoc(int n) { switch(n) { case 0: return '+'; case 1: return '-'; case 2: return '*'; case 3: return '/'; default: printf("error in itoc\n"); exit(0); } } void main(void) { int m,a,b,c,i,j,k,l; double n[4],ans; putchar('>'); scanf("%d",&m); file://それぞれの桁を配列nに代入 n[0]=(double)(m/1000); n[1]=(double)((m%1000)/100); n[2]=(double)((m%100)/10); n[3]=(double)(m%10); for(i=0;i<4;i++){ for(j=0;j<4;j++){ while(j==i) j++; if(j<4) for(k=0;k<4;k++){ while(k==i || k==j) k++; if(k<4) for(l=0;l<4;l++){ while(l==i || l==j || l==k) l++; if(l<4){ for(a=0;a<4;a++){ for(b=0;b<4;b++){ for(c=0;c<4;c++){ file://@@@NNNNの場合 ans=cal(cal(cal(n[i],n[j],c),n[k],b),n[l],a); if(9.9