プログラムを2つ作ってみた。
プログラムの実行結果は以下の通り。
1*2*3*456*7/8/9 = 19152 / 72 = 266
もう一つのプログラムの実行結果は以下の通り。
1*2*3*4 5 6*7/8/9
プログラムのソースは以下の通り。
#include "puzutl.h" struct struct_number { // 数字を通分して記録する int m; // 分子 int n; // 分母 struct_number() { m=n=0;} struct_number( int x) { m=x; n=1;} } dig[100]; int idig = 0; int op[100]; // 0:+, 1:-, 2:*, 3:/ int iop = 0; void push( int n) { dig[idig++] = n; } void calc( int p) { if( idig < 2) { pe( "Stack short\n"); exit(16);} int m1 = dig[idig-2].m, n1 = dig[idig-2].n; int m2 = dig[idig-1].m, n2 = dig[idig-1].n; idig--; int m, n; switch( p) { case 0: // + n = n1*n2; m = m1*n2 + n1*m2; dig[idig-1].m = m; dig[idig-1].n = n; //ps( "%d/%d + %d/%d = %d/%d\n", m1, n1, m2, n2, m, n); break; case 1: // − n = n1*n2; m = m1*n2 - n1*m2; dig[idig-1].m = m; dig[idig-1].n = n; //ps( "%d/%d - %d/%d = %d/%d\n", m1, n1, m2, n2, m, n); break; case 2: // × n = n1*n2; m = m1*m2; dig[idig-1].m = m; dig[idig-1].n = n; //ps( "%d/%d * %d/%d = %d/%d\n", m1, n1, m2, n2, m, n); break; case 3: // ÷ n = n1*m2; m = m1*n2; dig[idig-1].m = m; dig[idig-1].n = n; //ps( "%d/%d / %d/%d = %d/%d\n", m1, n1, m2, n2, m, n); break; default: pe( "unknown calc(%d)\n", p); exit(16); } } void ope( int p) { if( p == 2 || p == 3) { // ×,÷は出現したら即実行する calc( p); } else { // +または−は計算せずに取っておく if( p == 1) { dig[idig-1].m = -dig[idig-1].m; p = 0;}// −は+負数に変換する op[iop++] = p; } } cstring opestr( int o) { cstring s[] = { "+", "-", "*", "/" }; if( o >= 0 && o <= 3) return s[o]; return "?"; } void eval( cstring s) { cstring ss = s; iop = idig = 0; int n = 0; int num[100], o[100]; int inum = 0; while( *s) { if( *s == '+') { num[inum] = n; o[inum] = 0; inum++; n = 0; } else if( *s == '-') { num[inum] = n; o[inum] = 1; inum++; n = 0; } else if( *s == '*') { num[inum] = n; o[inum] = 2; inum++; n = 0; } else if( *s == '/') { num[inum] = n; o[inum] = 3; inum++; n = 0; } else { n *= 10; n += *s - '0'; } s++; } num[inum] = n; push(num[0]); for( int i=0; i< inum; i++) { push(num[i+1]); ope(o[i]); } while( iop--> 0) { calc(op[iop]); } if( dig[0].n != 0 && (dig[0].m / dig[0].n) == 266 && (dig[0].m % dig[0].n) == 0) { ps( "%s = %6d / %6d = %4d\n", ss, dig[0].m, dig[0].n, dig[0].m/dig[0].n); } } int main( int argc, cstring argv[]) { char ope[] = { '\0', '*', '/'}; // 途中に挟める演算は×と÷だけ,+,−は挟めない。'\0'は数字を連結するため。 char cal[100]; // 計算式をここに入れる。 astring p = cal; for( int a=0; a< sizeof(ope); a++) { *p++ = '1'; if(ope[a]) *p++ = ope[a]; // 演算子があるときは数字の間に挿入する for( int b=0; b< sizeof(ope); b++) { *p++ = '2'; if(ope[b]) *p++ = ope[b]; for( int c=0; c< sizeof(ope); c++) { *p++ = '3'; if(ope[c]) *p++ = ope[c]; for( int d=0; d< sizeof(ope); d++) { *p++ = '4'; if(ope[d]) *p++ = ope[d]; for( int e=0; e< sizeof(ope); e++) { *p++ = '5'; if(ope[e]) *p++ = ope[e]; for( int f=0; f< sizeof(ope); f++) { *p++ = '6'; if(ope[f]) *p++ = ope[f]; for( int g=0; g< sizeof(ope); g++) { *p++ = '7'; if(ope[g]) *p++ = ope[g]; for( int h=0; h< sizeof(ope); h++) { *p++ = '8'; if(ope[h]) *p++ = ope[h]; *p++ = '9'; *p = NIL; eval(cal); // 1〜9までの数字を使った式を評価する --p; // '9' の分 if(ope[h]) --p; --p; // '8' の分 } if(ope[g]) --p; --p; // '7' の分 } if(ope[f]) --p; --p; // '6' の分 } if(ope[e]) --p; --p; // '5' の分 } if(ope[d]) --p; --p; // '4' の分 } if(ope[c]) --p; --p; // '3' の分 } if(ope[b]) --p; --p; // '2' の分 } if(ope[a]) --p; --p; // '1' の分 } return 0; }
もう一つのプログラムのソースは以下の通り。
#include "puzutl.h" const int N = 9; int ope[N+1]; // 演算子 void find( char prev_ope, char new_ope, int n, int bunsi, int bunbo, int ope_val) // prev_ope :確定演算子(実際に計算する演算子) // new_ope :次の演算子(数字の連結を示すための' 'の場合もあるので必ず「演算子」という訳ではない) // n :1〜9までの数字 // bunsi,bunbo :現在までの計算結果(割り算があるので分子,分母で記憶する) // ope_val :被演算子(new_opeが' 'の場合演算を保留するのでnを計算に使えない) { if( n > N || new_ope != ' ') { // この時点までの計算式が確定する。 if( prev_ope == '*') bunsi = bunsi * ope_val; // 掛け算が分子のみに作用 if( prev_ope == '/') bunbo = bunbo * ope_val; // 割り算は分母のみに作用 prev_ope = new_ope; ope_val = n; } else { ope_val = ope_val * 10 + n; // 計算式が確定しないので被演算子は10倍して記憶 } if( n > N) { if( new_ope == ' ' && (bunsi/bunbo) == 266 && (bunsi%bunbo) == 0) { // 計算結果が266になるか? for( int i=1; i< n; i++) { ps( "%c", ope[i]); ps( "%d", i); } ps( "\n"); } return; } ope[n] = new_ope; // 演算子を記憶しておく find( prev_ope, ' ', n+1, bunsi, bunbo, ope_val); find( prev_ope, '*', n+1, bunsi, bunbo, ope_val); find( prev_ope, '/', n+1, bunsi, bunbo, ope_val); } int main( int argc, cstring argv[]) { find( ' ', ' ', 1, 1, 1, 0); return 0; }