/* (c) Dr. David Alan Gilbert (prolog@treblig.org) This program solves the 'Su Doku' puzzles from www.sudoku.com and as currently published in The Times. (Apparently this is an old Japanese puzzle that can have grids of any size). It uses the Finite Domain solver facilities in GNU Prolog. (It is my first Prolog program for more than 10 years so suggesions welcome). 26/12/2004 The puzzle is a 9x9 grid organised into 3x3 squares. The rules are: All rows must contain the digits 1..9 unrepeated All columns must contain the digits 1..9 unrepeated All 3x3 squares must contain the digits 1..9 unrepeated Some of the puzzles can be rather good mental exercise! Here is an example run: | ?- sudokufd([6,_,_,1,3,_,_,_,7,5,7,_,6,_,_,_,_,_,9,_,1,_,2,_,3,_,_,_,4,_,_,_,_,2,_,_,1,_,_,_,5,_,_,_,9,2,_,_,_,4,6,_,_,1,_,_,_,9,_,_,_,_,8,_,6,_,_,7,_,_,_,_,8,_,_,4,1,_,5,_,3]). [6,2,4][1,3,5][9,8,7] [5,7,3][6,8,9][4,1,2] [9,8,1][7,2,4][3,5,6] --------------------- [7,4,6][8,9,1][2,3,5] [1,3,8][2,5,7][6,4,9] [2,5,9][3,4,6][8,7,1] --------------------- [4,1,5][9,6,3][7,2,8] [3,6,2][5,7,8][1,9,4] [8,9,7][4,1,2][5,6,3] true ? ; (4 ms) no (I'm not sure if this one is hard on paper - I just used the program to make it up). */ validSet(S) :- fd_all_different(S). /* See if a square is valid - takes 3 lists of 3 */ validSquare(A,B,C) :- append(A,B,T1), append(C,T1,T2), validSet(T2). /* Takes 9 lists of 3 and an integer index - checks a whole * column */ validColumn([A,B,C,D,E,F,G,H,I],Index) :- nth(Index, A, Ae), nth(Index, B, Be), nth(Index, C, Ce), nth(Index, D, De), nth(Index, E, Ee), nth(Index, F, Fe), nth(Index, G, Ge), nth(Index, H, He), nth(Index, I, Ie), validSet([Ae,Be,Ce,De,Ee,Fe,Ge,He,Ie]). /* Take in a 3 element list and spit out the elements individually */ split3list(In,A,B,C) :- length(In,3), nth(1,In,A), nth(2,In,B), nth(3,In,C). /* Takes a list in, strips the first 9 elements off and returns * them as 3 lists of 3 and another list with the remaining * elements */ splitList39(In, Remains, Out1, Out2, Out3) :- append(T1, Remains, In), length(T1, 9), append(Out1,T2 , T1), length(Out1,3), append(Out2,Out3 , T2), length(Out2,3), length(Out3,3). /* Write the result out in a format similar to the printed format */ writeResult(L) :- splitList39(L, T1, A1,A2,A3), splitList39(T1, T2, B1,B2,B3), splitList39(T2, T3, C1,C2,C3), splitList39(T3, T4, D1,D2,D3), splitList39(T4, T5, E1,E2,E3), splitList39(T5, T6, F1,F2,F3), splitList39(T6, T7, G1,G2,G3), splitList39(T7, T8, H1,H2,H3), splitList39(T8, [], I1,I2,I3), write(A1), write(A2), write(A3),nl, write(B1), write(B2), write(B3),nl, write(C1), write(C2), write(C3),nl, write('---------------------'),nl, write(D1), write(D2), write(D3),nl, write(E1), write(E2), write(E3),nl, write(F1), write(F2), write(F3),nl, write('---------------------'),nl, write(G1), write(G2), write(G3),nl, write(H1), write(H2), write(H3),nl, write(I1), write(I2), write(I3),nl. /* Takes one list of 81 elements - rows then columns */ sudokufd(L) :- fd_domain(L,1,9), splitList39(L, T1, A1,A2,A3), splitList39(T1, T2, B1,B2,B3), splitList39(T2, T3, C1,C2,C3), splitList39(T3, T4, D1,D2,D3), splitList39(T4, T5, E1,E2,E3), splitList39(T5, T6, F1,F2,F3), splitList39(T6, T7, G1,G2,G3), splitList39(T7, T8, H1,H2,H3), splitList39(T8, [], I1,I2,I3), /* Check rows */ append(A1,A2,At1), append(At1,A3,At2), validSet(At2), append(B1,B2,Bt1), append(Bt1,B3,Bt2), validSet(Bt2), append(C1,C2,Ct1), append(Ct1,C3,Ct2), validSet(Ct2), append(D1,D2,Dt1), append(Dt1,D3,Dt2), validSet(Dt2), append(E1,E2,Et1), append(Et1,E3,Et2), validSet(Et2), append(F1,F2,Ft1), append(Ft1,F3,Ft2), validSet(Ft2), append(G1,G2,Gt1), append(Gt1,G3,Gt2), validSet(Gt2), append(H1,H2,Ht1), append(Ht1,H3,Ht2), validSet(Ht2), append(I1,I2,It1), append(It1,I3,It2), validSet(It2), /* Check squares */ validSquare(A1,B1,C1), validSquare(A2,B2,C2), validSquare(A3,B3,C3), validSquare(D1,E1,F1), validSquare(D2,E2,F2), validSquare(D3,E3,F3), validSquare(G1,H1,I1), validSquare(G2,H2,I2), validSquare(G3,H3,I3), /* Check columns */ validColumn([A1,B1,C1,D1,E1,F1,G1,H1,I1],1), validColumn([A1,B1,C1,D1,E1,F1,G1,H1,I1],2), validColumn([A1,B1,C1,D1,E1,F1,G1,H1,I1],3), validColumn([A2,B2,C2,D2,E2,F2,G2,H2,I2],1), validColumn([A2,B2,C2,D2,E2,F2,G2,H2,I2],2), validColumn([A2,B2,C2,D2,E2,F2,G2,H2,I2],3), validColumn([A3,B3,C3,D3,E3,F3,G3,H3,I3],1), validColumn([A3,B3,C3,D3,E3,F3,G3,H3,I3],2), validColumn([A3,B3,C3,D3,E3,F3,G3,H3,I3],3), fd_labeling(L), writeResult(L).