プログラム実行結果は以下の通り。
init: 7 1 6 -8 -9 = 699 remove .-.|.-.|.-.|.-.|.-.|.-.|.-.| -.-|-.-|-.-|-.-|-.-|-.-|-.-| .-.|.-.|.-.|.-.|.-.|.X.|.-.| -.-|-.-|-.-|-.-|-.-|-.-|-.-| .-.|.-.|.-.|.-.|.-.|.-.|.-.| remove .-.|.-.|.-.|.-.|.-.|.-.|.-.| -.-|-.-|-.-|-.-|-.X|-.-|-.-| .-.|.-.|.-.|.-.|.-.|.-.|.-.| -.-|-.-|-.-|-.-|-.-|-.-|-.-| .-.|.-.|.-.|.-.|.-.|.-.|.-.| add .-.|.-.|.-.|.-.|.-.|.-.|.-.| -.-|-.-|-.-|-.-|-.-|-.X|-.-| .-.|.-.|.-.|.-.|.-.|.-.|.-.| -.-|-.-|-.-|-.-|-.-|-.-|-.-| .-.|.-.|.-.|.-.|.-.|.-.|.-.| add .-.|.-.|.-.|.-.|.-.|.-.|.-.| -.-|-.-|-.-|-.-|-.-|-.-|-.-| .-.|.-.|.-.|.-.|.-.|.-.|.-.| -.-|-.-|-.-|-.-|-.-|-.X|-.-| .-.|.-.|.-.|.-.|.-.|.-.|.-.| result: 7 1 6 -6 1 9 = 97
これを図にすると以下のようになる。
プログラムのソースは以下の通り。
#include "puzutl.h" #include <math.h> const ulong bit0 = 0x00000001; const ulong bit1 = 0x00000002; const ulong bit2 = 0x00000004; const ulong bit3 = 0x00000008; const ulong bit4 = 0x00000010; const ulong bit5 = 0x00000020; const ulong bit6 = 0x00000040; // bit 0 1 2 3 4 5 6 7 8 9 - // .0. .0. ... .0. .0. ... .0. .0. .0. .0. .0. ... // 1.2 1.2 ..2 ..2 ..2 1.2 1.. 1.. 1.2 1.2 1.2 ... // .3. .3. ... .3. .3. .3. .3. .3. ... .3. .3. .3. // 4.5 4.5 ..5 4.. ..5 ..5 ..5 4.5 ..5 4.5 ..5 ... // .6. .6. ... .6. .6. ... .6. .6. ... .6. .6. ... // 0 1 2 3 4 5 6 7 8 9 '-' int _i2b[] = { 0x77, 0x24, 0x5d, 0x6d, 0x2e, 0x6b, 0x7b, 0x27, 0x7f, 0x6f, 0x08}; // 数字をビット表現に変換するためのテーブル int _b2i[0x7F+10]; // ビット表現を数字に変換するためのテーブル(_i2b[]を逆に見る,main()で初期設定) int i2b( int n) // 数字をビット表現に変換する { assert( n >= 0 && n <= 10); // n==10は'-' return _i2b[n]; } int b2i( int b) // ビット表現を数字に変換する { assert( (b&~0x7F) == 0); return _b2i[b]; // _b2i[]は_i2b[]を使って初期化しておく必要がある } int64 makebit( int v, int shift) // 1個の数字が7ビット,それを49ビット中に7個入れることが出来る { int64 v64 = v; assert( (v&~0x7F)==0); v64 <<= (shift*7); // 1つの数字で7ビット return v64; } int64 bit64( int p) // bit<p> を求める { int64 b = 1; b <<= p; return b; } int eval( int64 e) // 計算式を評価する { int v[7]; // 取り出した7個の数字を入れる予定 for( int i=0; i< 7; i++) { // 右から順に数字を取り出す int val = e & 0x7F; // 7ビット取り出し v[i] = b2i(val); // それを数値に変換する if( v[i] < 0) return -1; // 変換できない数字が出現した e >>= 7; // 次に取り出す数値 } // v[0]〜v[6]に取り出した数字が入っている,v[0]が一番右の数字 int n = 0; // 数字の個数 int N[7] = {0}; // 出現数字 int sign = 1; // 出現数字の符号 if( v[6] == 0) return -1; // 先頭の数字が0の場合は題意に沿わない for( i=0; i< 7; i++) { int val = v[7-i-1]; // 左の数字から取り出す if( val == 10) { // '-'が出現した n++; // 以降,新しい数字と見なす sign = -1; // 負数が出現したことになる continue; // 次の数字を見に行く } N[n] *= 10; // N[n] += val * sign; // 負数の場合も考慮して数字を評価する } int result = 0; for( i=0; i<= n; i++) { // 計算する result += N[i]; // 負数はマイナスでN[i]に入っているので足すだけで済む。 } return result; // 計算結果 } void b2buf( char buf[7][5][3], int idx, int v) { for( int row=0; row< 5; row++) { for( int col=0; col< 3; col++) { buf[idx][row][col] = '.'; } } if( v & bit0) buf[idx][0][1] = 'X'; else buf[idx][0][1] = '-'; if( v & bit1) buf[idx][1][0] = 'X'; else buf[idx][1][0] = '-'; if( v & bit2) buf[idx][1][2] = 'X'; else buf[idx][1][2] = '-'; if( v & bit3) buf[idx][2][1] = 'X'; else buf[idx][2][1] = '-'; if( v & bit4) buf[idx][3][0] = 'X'; else buf[idx][3][0] = '-'; if( v & bit5) buf[idx][3][2] = 'X'; else buf[idx][3][2] = '-'; if( v & bit6) buf[idx][4][1] = 'X'; else buf[idx][4][1] = '-'; } void dump( cstring msg, int v) // bitの立っている位置を'X'で出力する { char buf[7][5][3]; // buf[7個の数字][縦][横] for( int i=0; i< 7; i++) { b2buf( buf, 7-i-1, v&0x7F); v >>= 7; } ps( "%s\n", msg); // 以下のような出力をする。ちょっと判りづらいけど我慢。 // .-.|.-.|.-.|.-.|.-.|.-.|.-.| // -.-|-.-|-.-|-.-|-.-|-.-|-.-| // .-.|.-.|.-.|.-.|.-.|.-.|.-.| // -.-|-.-|-.-|-.-|-.-|-.X|-.-| // .-.|.-.|.-.|.-.|.-.|.-.|.-.| for( int row=0; row< 5; row++) { for( int idx=0; idx< 7; idx++) { for( int col=0; col< 3; col++) { ps( "%c", buf[idx][row][col]); } ps( "|"); } ps( "\n"); } ps( "\n"); } void dump49( cstring msg, int64 v) // 式を評価して出力する { int R = eval(v); int val[7]; for( int i=0; i< 7; i++) { val[7-i-1] = v & 0x7F; v >>= 7; } ps( "%s: ", msg); for( i=0; i< 7; i++) { int n = b2i(val[i]); //if( n < 0) ps( "(%d,%d)", n, val[i]); if( n == 10) ps( "-"); else ps( "%d ", n); } if( R > 0) ps( "= %d\n", R); else ps( "= ERROR(%d)\n", R); } int main( int argc, cstring argv[]) { for( int i=0; i< 0x7F+10; i++) { _b2i[i] = -1; } for( i=0; i<= 10; i++) { // 0〜9と10=='-' _b2i[_i2b[i]] = i; } int64 A, B, C, D, E; int64 mA, mE; int v, minv = 9999999, ma, mb, mc, md; // 最小値と取り出す棒 int64 b49 = makebit( i2b( 7),6)| makebit( i2b( 1),5)| makebit( i2b( 6),4)| makebit( i2b(10),3)| // 10は'-' makebit( i2b( 8),2)| makebit( i2b(10),1)| // 10は'-' makebit( i2b( 9),0); A = b49; for( int a=0; a< 49; a++) { if( !(bit64(a) & A)) continue; // 使われていない棒を調べようとしている B = A & ~bit64(a); for( int b=0; b< 49; b++) { if( !(bit64(b) & B)) continue; // 使われていない棒を調べようとしている C = B & ~bit64(b); for( int c=0; c< 49; c++) { if( bit64(c) & C) continue; // 既にこの棒は使っている D = C | bit64(c); for( int d=0; d< 49; d++) { if( bit64(d) & D) continue; // 既にこの棒は使っている E = D | bit64(d); int v = eval(E); // 計算式を評価する,負数は計算不可または最初の数が0 if( v > 0 && v < minv) { // 最小値を求める minv= v; ma = a, mb = b, mc = c, md = d; mA = A, mE = E; } } } } } dump49("init", mA); dump("remove", bit64(ma)); dump("remove", bit64(mb)); dump("add", bit64(mc)); dump("add", bit64(md)); dump49("result", mE); return 0; }