Alla simppeli iterativinen Sudokun ratkaisija. Anna ohjelmalle komentoriviparametrina Sudokun sisältämän tekstitiedoston nimi.
\
\ Simple iterative backtracking Sudoku solver for 8th
\
needs array/each-slice
[ 00, 00, 00, 03, 03, 03, 06, 06, 06,
00, 00, 00, 03, 03, 03, 06, 06, 06,
00, 00, 00, 03, 03, 03, 06, 06, 06,
27, 27, 27, 30, 30, 30, 33, 33, 33,
27, 27, 27, 30, 30, 30, 33, 33, 33,
27, 27, 27, 30, 30, 30, 33, 33, 33,
54, 54, 54, 57, 57, 57, 60, 60, 60,
54, 54, 54, 57, 57, 57, 60, 60, 60,
54, 54, 54, 57, 57, 57, 60, 60, 60 ] constant top-left-cell
\ Bit number presentations
a:new 2 b:new b:clear a:push ( 2 b:new b:clear swap 1 b:bit! a:push ) 0 8 loop constant posbit
: posbit? \ n -- s
posbit swap a:@ nip ;
: search \ b -- n
null swap
( dup -rot b:bit@ if rot drop break else nip then ) 0 8 loop
swap ;
: b-or \ b b -- b
' n:bor b:op ;
: b-and \ b b -- b
' n:band b:op ;
: b-xor \ b b -- b
b:xor
[ xff, x01 ] b:new
b-and ;
: b-not \ b -- b
xff b:xor
[ xff, x01 ] b:new
b-and ;
: b-any \ a -- b
' b-or 0 posbit? a:reduce ;
: row \ a row -- a
9 n:* 9 a:slice ;
: col \ a col -- a
-1 9 a:slice+ ;
\ For testing sub boards
: sub \ a n -- a
top-left-cell swap a:@ nip over over 3 a:slice
-rot 9 n:+ 2dup 3 a:slice
-rot 9 n:+ 3 a:slice
a:+ a:+ ;
a:new 0 args "Give Sudoku text file as param" thrownull
f:slurp "Cannot read file" thrownull >s "" s:/
' >n a:map ( posbit? a:push ) a:each! drop constant board
: display-board
board ( search nip -1 ?: n:1+ ) a:map
"+-----+-----+-----+\n"
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"+-----+-----+-----+\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"+-----+-----+-----+\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"+-----+-----+-----+\n" s:+
s:strfmt . ;
\ Store move history
a:new constant history
\ Possible numbers for a cell
: candidates? \ n -- s
dup dup 9 n:/ n:int swap 9 n:mod \ row col
board swap col b-any
board rot row b-any
b-or
board rot sub b-any
b-or
b-not ;
\ If found: -- n T
\ If not found: -- T
: find-free-cell
false
board ( 0 posbit? b:= if nip true break else drop then ) a:each drop ;
: validate
true
board
( dup -rot a:@ swap 2 pick 0 posbit? a:! 2 pick candidates? 2 pick b:= if
-rot a:!
else
2drop drop
false swap
break
then ) 0 80 loop drop ;
: solve
repeat
find-free-cell if
dup candidates?
repeat
search null? if
drop board -rot a:! drop
history a:len 0 n:= if
drop false ;;
then
a:pop nip
a:open
else
n:1+ posbit?
dup
board 4 pick rot a:! drop
b-xor
2 a:close
history swap a:push drop
break
then
again
else
validate
break
then
again ;
: app:main
"Sudoku puzzle:\n" .
display-board cr
solve if
"Sudoku solved:\n" .
display-board
else
"No solution!\n" .
then ;Ohjelman esimerkkitulostus:
C:\temp\8sudoku>8th sudoku.8th puzzle.txt Sudoku puzzle: +-----+-----+-----+ |0 0 0|5 9 0|0 0 0| |2 3 0|0 0 4|0 0 1| |0 0 0|8 0 0|0 0 3| +-----+-----+-----+ |0 0 2|0 0 0|0 0 0| |0 5 0|0 0 2|0 0 6| |4 1 6|7 0 0|0 8 0| +-----+-----+-----+ |8 0 7|0 0 0|0 0 0| |0 0 9|0 6 7|0 3 4| |0 0 0|0 0 0|0 7 9| +-----+-----+-----+ Sudoku solved: +-----+-----+-----+ |1 7 4|5 9 3|2 6 8| |2 3 8|6 7 4|5 9 1| |6 9 5|8 2 1|7 4 3| +-----+-----+-----+ |9 8 2|4 1 6|3 5 7| |7 5 3|9 8 2|4 1 6| |4 1 6|7 3 5|9 8 2| +-----+-----+-----+ |8 6 7|3 4 9|1 2 5| |5 2 9|1 6 7|8 3 4| |3 4 1|2 5 8|6 7 9| +-----+-----+-----+ C:\temp\8sudoku>
Aihe on jo aika vanha, joten et voi enää vastata siihen.