digitalmars.D.learn - Programming Puzzle 8-8-08
- Wyverex (60/60) Aug 08 2008 Another day, another puzzle!! I'll try keeping this up as long as I can...
- Wyverex (108/108) Aug 08 2008 //Heres a backtracking solution
- Steven Schveighoffer (273/273) Aug 08 2008 Depth-first brute force with the standard sudoku constraints
- BCS (200/200) Aug 08 2008 Reply to wyverex,
Another day, another puzzle!! I'll try keeping this up as long as I can! Write a program that can solve Sudoku! http://en.wikipedia.org/wiki/Sudoku the input... char[][] boards = ["000075400000000008080190000300001060000000034000068170204000603900000020530200000", "300000000050703008000028070700000043000000000003904105400300800100040000968000200", "302609005500730000000000900000940000000000109000057060008500006000000003019082040", "530000008007000030200006901000500200090370004000981000300040560000090000000007080", "008310900095000160000000005000400000000080049006072000000001030000240607001008200", "000400970000051600042000010030000000070508064000070000700030000300090000005864009", "060500000720000000000000320000050637000004500000230180180009000603070000004006003", "274000030000000005000600041900306000100280000006054000000000002007000583000095700", "570000069000003800090000000801600000000030600702000050000060501000702000006091032", "005200000400300700600000010800020100040800500000095000083040070090006080500902000", "400500600200000000000020000002004380000030000790000504000060490070093810500100030", "000790000001000000040050080000800027009003000000020403000040600004907100600501790", "060010000403700008520640000002000000009438005000006300004301200000200000005070000", "130400000705300000600020000000000027000900400000000085860500003059103000002004060", "020001048400000037071006020500000000000010802000809500090030400000040000000902060", "000000020006410035180020000008130406020000300600000000790005000004000008001300002", "040000200000007090000006010870020004901000028060030100006800041000070050005900000", "000030009048900000200470100125000080000080710000500000000090054061000003000050070", "000000060306000000000000805000605071005000300100870042900200014201080000000703000", "900000586008070004401000300002010900804005100000007000003008702000000000600040009", "000032970070045010000800000001060000000000000029000840500620007004000009100009036", "950003008800002000031000000060350090010007050000060010008000307000206009007000004", "000000000300027801100083000005001000001370060007004002200060070004000000900030650", "030207001000180670001030050000500900190004008000600020300700000000005080000020006", "600000004020507000000000031010900060000350109800000002240108000067090000003000006", "600095000000061802000000100500016000004000200002008036000002450040050000003400070", "201070800460000090080010040000050030030980051000006000004097000500000000090020700", "090000030100000800000312700050640007000730240080500000026000010000004300000050060", "000560300100000800024000000009000000080720006610800000007206000400080037000104090", "090035406001000000007000089070940050100200000006800700008004030000600040605000000", "050060040006247091000190000000600900200000084000300005031000008000000006004000250"]; output... 000075400 693875412 000000008 145632798 080190000 782194356 300001060 357421869 000000034 = 816957234 000068170 429368175 204000603 274519683 900000020 968743521 530200000 531286947 300000000 387419526 050703008 259763418 000028070 641528379 700000043 716285943 000000000 = 594631782 003904105 823974165 400300800 472396851 100040000 135842697 968000200 968157234 302609005 382619475 500730000 594738621 000000900 176425938 000940000 863941752 000000.......
Aug 08 2008
//Heres a backtracking solution import tango.io.Stdout; char[][] boards = ["000075400000000008080190000300001060000000034000068170204000603900000020530200000", "300000000050703008000028070700000043000000000003904105400300800100040000968000200", "302609005500730000000000900000940000000000109000057060008500006000000003019082040", "530000008007000030200006901000500200090370004000981000300040560000090000000007080", "008310900095000160000000005000400000000080049006072000000001030000240607001008200", "000400970000051600042000010030000000070508064000070000700030000300090000005864009", "060500000720000000000000320000050637000004500000230180180009000603070000004006003", "274000030000000005000600041900306000100280000006054000000000002007000583000095700", "570000069000003800090000000801600000000030600702000050000060501000702000006091032", "005200000400300700600000010800020100040800500000095000083040070090006080500902000", "400500600200000000000020000002004380000030000790000504000060490070093810500100030", "000790000001000000040050080000800027009003000000020403000040600004907100600501790", "060010000403700008520640000002000000009438005000006300004301200000200000005070000", "130400000705300000600020000000000027000900400000000085860500003059103000002004060", "020001048400000037071006020500000000000010802000809500090030400000040000000902060", "000000020006410035180020000008130406020000300600000000790005000004000008001300002", "040000200000007090000006010870020004901000028060030100006800041000070050005900000", "000030009048900000200470100125000080000080710000500000000090054061000003000050070", "000000060306000000000000805000605071005000300100870042900200014201080000000703000", "900000586008070004401000300002010900804005100000007000003008702000000000600040009", "000032970070045010000800000001060000000000000029000840500620007004000009100009036", "950003008800002000031000000060350090010007050000060010008000307000206009007000004", "000000000300027801100083000005001000001370060007004002200060070004000000900030650", "030207001000180670001030050000500900190004008000600020300700000000005080000020006", "600000004020507000000000031010900060000350109800000002240108000067090000003000006", "600095000000061802000000100500016000004000200002008036000002450040050000003400070", "201070800460000090080010040000050030030980051000006000004097000500000000090020700", "090000030100000800000312700050640007000730240080500000026000010000004300000050060", "000560300100000800024000000009000000080720006610800000007206000400080037000104090", "090035406001000000007000089070940050100200000006800700008004030000600040605000000", "050060040006247091000190000000600900200000084000300005031000008000000006004000250"]; void main() { foreach(org; boards) { auto sol = solve( org.dup, 0 ); for(int x = 0; x <81; x+=9) Stdout.formatln("{} {} {}", org[x..x+9], (x == 4*9 ? "=": " "), sol[x..x+9]); Stdout.newline; } } char[] solve( char[] board, int index ) { if( index >= 81 ) return board; if( board[index] != '0' ) return solve( board, index + 1 ); for( int i = 1; i < 10; i++ ) { board[index] = i + '0'; if( !test( board, index ) ) continue; auto ans = solve( board, index + 1 ); if( ans !is null ) return ans; } board[index] = '0'; return null; } bool test( char[] board, int index ) { //tests if the new number is legal int x = index % 9; int y = index / 9; //test what row the number is in { int[10] find; for(int i = y*9; i < y*9+9; i++) { int n = board[i] - '0'; if(n == 0) continue; if(find[n] == 1) return false; find[n] = 1; } } //test the column { int[10] find; for( int i = 0; i < 9; i++ ) { int n = board[i*9 + x] - '0'; if(n == 0) continue; if(find[n] == 1) return false; find[n] = 1; } } //now to test the local block { int bx = x / 3; int by = y / 3; int[10] find; for( int yy = by * 3; yy < (by * 3) + 3; ++yy ) { for( int xx = bx*3; xx < (bx * 3) + 3; ++xx ) { int i = yy*9+xx; int n = board[i] - '0'; if(n == 0) continue; if(find[n] == 1) return false; find[n] = 1; } } } return true; }
Aug 08 2008
Depth-first brute force with the standard sudoku constraints Code: import tango.io.Stdout; char[][] boards = [...]; bool solve(int[][] brd, int idx) { if(idx == 9 * 9) return true; int x = idx % 9; int y = idx / 9; if(brd[x][y]) return solve(brd, idx + 1); bool[10] bad; for(int i = 0; i < 9; i++) { bad[brd[x][i]] = true; bad[brd[i][y]] = true; } int boxx = (x / 3) * 3; int boxy = (y / 3) * 3; for(int i = 0; i < 3; i++) for(int j = 0; j < 3; j++) bad[brd[boxx + i][boxy + j]] = true; for(int i = 1; i < 10; i++) if(!bad[i]) { brd[x][y] = i; if(solve(brd, idx + 1)) return true; } brd[x][y] = 0; return false; } void printboard(int[][] brd) { for(int i = 0; i < 9; i++) { if(i % 3 == 0) Stdout.newline; for(int j = 0; j < 9; j++) { if(j % 3 == 0) Stdout(" "); Stdout(brd[i][j]); } Stdout.newline; } } void main() { for(int i = 0; i < boards.length; i++) { int[][] brd = new int[][](9,9); for(int j = 0; j < 9; j++) for(int k = 0; k < 9; k++) brd[j][k] = boards[i][j * 9 + k] - '0'; Stdout("=======================").newline; printboard(brd); solve(brd, 0); Stdout.newline; printboard(brd); } } Output is attached (for comparison) run time: real 0m1.797s user 0m1.794s sys 0m0.003s -Steve begin 666 sudoku.txt M,R U,C$-"B U,S$ ,C V(#DT-PT*/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T- M"B W,38 ,C U(#DT M-S0 ,3 V(#DU M-#DR M.#DQ M,PT*(#DT M"B P,#D M/3T]/3T]/3T]/3T]/3T]/3T-" T*(#DP M/3T]/3T]/3T]/3T]/3T-" T*(#DU M,C U(#DV- M." U,S8-" T*(#DX-B M,S8 -#DW M(#DX-2 ` end
Aug 08 2008
Reply to wyverex, It's not taking input in the correct format, but I do think I'll tie for the easiest solution as All I had to do was copy it from an old NG post of mine: BTW 2.7 ms per program run las I checked. import std.stdio; import std.string; import std.cstream; struct Game { char[81] value; ushort[81] mask; int count; int working; int guess; ushort guessMask; } //bool[81] changed; class Block:Error{this(char[]c){super(c);}} int main() { Game current; Game[81] stack; int at; int iter; void Report(int z) { static char[] value = ".123456789"; debug writef( " depth = %d found = %d iterations = %d working = %d guess = %d\n\n", at, current.count, iter, current.working, current.guess); for(int y = 0; y < 9; y++) { for(int x = 0; x < 9; x++) { writef("%d ",// value[ current.value[y*9+x]);//]); if(2 == x%3) writef(" "); } writef("\n"); if(2 == y%3) writef("\n"); } debug for(int y = 0; y < 9; y++) { for(int x = 0; x < 9; x++) { int i = 0; ushort t = current.mask[y*9+x]; for(int z=0; z<9; z++) { writef((t & 0x0100) ? "." : "!"); i+=(t & 0x0100) ? 0 : 1; t<<=1; } writef("%d ",i); if(2 == x%3) writef(" "); } writef("\n"); if(2 == y%3) writef("\n"); } }; // int loop = 0; restart: loop++; at=0; current.count=0; current.working = -1; for(int i = 0; i<81; i++) { current.value[i] = 0; current.mask[i] = 0x0; } static byte[81] seeds = [ 0, 0, 0, 0, 0, 7, 4, 0, 2, 7, 0, 0, 6, 0, 0, 0, 5, 8, 0, 0, 5, 0, 8, 2, 0, 0, 0, 0, 0, 8, 4, 0, 0, 0, 0, 7, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 1, 9, 0, 0, 0, 0, 0, 7, 3, 0, 6, 0, 0, 9, 7, 0, 0, 0, 5, 0, 0, 3, 1, 0, 3, 8, 0, 0, 0, 0, 0 ]; foreach(int i, c;seeds) setValue(current, i, c); // Report(0); writef(\n\n); bool delta; int v; do { do { delta = false; for(int c=0; c<80; c++) { switch(current.mask[c]) { case 0x01ff: goto backUp; default: case 0xffff: continue; case 0x00ff: v = 9; break; case 0x017f: v = 8; break; case 0x01bf: v = 7; break; case 0x01df: v = 6; break; case 0x01ef: v = 5; break; case 0x01f7: v = 4; break; case 0x01fb: v = 3; break; case 0x01fd: v = 2; break; case 0x01fe: v = 1; break; } setValue(current, c, v); delta = true; } }while (delta) while(false) // skip this block unless we get here by goto { backUp: assert(0 < at); at--; current = stack[at]; current.mask[current.working] ^= current.guessMask; debug writef("<<<<< backup %d\n", at); } with(current) { // find a unknown cell while(working == -1 || 0 != value[working]) { working++; guess = 1; guessMask = 0x01; } // find an avalable value while(0 != (mask[working] & guessMask)) { guess++; guessMask<<=1; if(9 < guess) goto backUp; } } // store off state stack[at] = current; at++; debug writef("cell=%d guess=%d\n", current.working, current.guess); //make move setValue(current, current.working, current.guess); iter++; }while(current.count < 81) // if(loop<1000) goto restart; Report(0); return 0; } byte[20][81] depends; static this() { int at; for(int set = 0; set<81; set++) { at=0; for(int to = 0; to<81; to++) { if(set == to) continue; if( set/9 == to/9 || set%9 == to%9 || ( (set/3)%3 == (to/3)%3 && set/27 == to/27 ) ) depends[set][at++] = to; } assert(at == 20); } } bool setValue(inout Game where, int what, int to) { if(0 == to || 9 < to) return false; bool ret = false; short mask = 0x0001 << (to-1); // if(where.value[what] || where.mask[what] & mask) throw new Error(__FILE__":" ~ itoa!(__LINE__)~" error\n"); where.value[what] = to; where.mask[what] = 0xffff; where.count++; foreach(c;depends[what]) where.mask[c] |= mask; return ret; } template decimalDigit(int n){const char[] decimalDigit = "0123456789"[n..n+1];} template itoa(long n){ static if (n < 0) const char[] itoa = "-" ~ itoa!(-n); else static if (n < 10) const char[] itoa = decimalDigit!(n); else const char[] itoa = itoa!(n/10L) ~ decimalDigit!(n%10L); }
Aug 08 2008