<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">
% Sudoku
% Martti Meri
% 13.10.2005

% full Sudoku table
% sudim(3).
% 4X4 table
% sudim(2).

:-dynamic sudim/1.

suset(S) :-
    sudim(SD),
    L is SD * SD,
    numlist(1,L,S).

bad_cell(S,I,J,X) :-
    member([I2,J2,X2],S),
    sudim(SD),
    CI is ((I-1) // SD),
    CI2 is ((I2-1) // SD),
    CJ is ((J-1) // SD), 
    CJ2 is ((J2-1) // SD),
    CI = CI2,
    CJ = CJ2,
    X = X2.

randlist(F,F,L) :-
    length(F,L),
    !.

randlist(F,Resu,L) :-
    X is random(L) + 1,
    \+member(X,F),
    !,
    randlist([X | F],Resu,L).

randlist(F,Resu,L) :-
    randlist(F,Resu,L).

initJ(S,_,L,S) :-
    sudim(SD),
    L1 is ((SD * SD) + 1),
    L = L1.

initJ(S,I,J,R) :-
    JP is J + 1,
    sudim(SD),
    L is SD * SD,
    randlist([],SS,L),
    member(X,SS),
    \+member([I,J,_],S),
    \+member([I,_,X],S),
    \+member([_,J,X],S),
    \+bad_cell(S,I,J,X),
    initJ([[I,J,X]|S],I,JP,R).

initI(S,L,S) :-
    sudim(SD),
    L1 is ((SD * SD) + 1),
    L = L1.

initI(S,I,R) :-
    initJ(S,I,1,R1),
    IP is I+1,
    initI(R1,IP,R).

printI([]) :- 
    nl.

printI([[I,J,X] | T]) :-
    sudim(SD),
    JD is SD * SD,
    J = JD,
    !,
    printI(T),
    write([I,J,X]),
    nl.

printI([[I,J,X] | T]) :-
    printI(T),
    write([I,J,X]),
    tab(1).

printT([]).
printT([H |Tasks]) :-
        format('step ~w sets item[ ~w , ~w ] to value ~w \n',H),
        printT(Tasks).        


% piilotetaan 100 - Prob % kentistä (0 &lt; Prob &lt; 100) 
hide([],_,[]).
hide([[I,J,_] | T], Prob,[[I,J,0] | T2]) :-
    R is random(100) + 1,
    R &gt; Prob,
    !,
    hide(T,Prob,T2).
hide([[I,J,X] | T], Prob,[[I,J,X] | T2]) :-
    hide(T,Prob,T2).

% kerätään tietyillä riveillä ja sarakkeilla olevien arvojen joukkoja
row_items([],_,[]).
row_items([[I,_,X] | T],I,[X | Used]) :-
    X &gt; 0,
    !,
    row_items(T,I,Used).
row_items([[I,_,_] | T],I,Used) :-
    row_items(T,I,Used),
    !.
row_items([[_,_,_] | T],Row,Used) :-
    row_items(T,Row,Used).

col_items([],_,[]).
col_items([[_,J,X] | T],J,[X | Used]) :-
    X &gt; 0,
    !,
    col_items(T,J,Used).
col_items([[_,J,_] | T],J,Used) :-
    col_items(T,J,Used),
    !.
col_items([[_,_,_] | T],Row,Used) :-
    col_items(T,Row,Used).

% ehto samassa alimatriisissa olemiselle
same_sub(S,[I1,J1,_],[I2,J2,V2]) :-
    member([I2,J2,V2],S),
    sudim(SD),
    CI1 is ((I1-1) // SD),
    CI2 is ((I2-1) // SD),
    CJ1 is ((J1-1) // SD), 
    CJ2 is ((J2-1) // SD),
    CI1 = CI2,
    CJ1 = CJ2.

% haetaan samassa alimatriisissa olevien kenttien tiedot
cel_items(S,I,J, Used) :-
    member([I,J,X],S),
    setof([L,M,N],same_sub(S,[I,J,X],[L,M,N]),Cella),
    setof(N,member([_,_,N],Cella),Used1),
    ((X &gt; 0, Used = [ X | Used1]);(X=0 , Used = Used1)).
        

%  muodostetaan Available lista jossa kentän I,J kannalta
%  vielä käytettävissä olevat arvot

item_values_available(S,I,J,Available) :-
    member([I,J,0],S),
    row_items(S,I,RUsed),
    col_items(S,J,CUsed),
    cel_items(S,I,J,SUsed),
    union(RUsed,CUsed,Temp1),
    union(Temp1,SUsed,Used),
    suset(All),
    subtract(All,Used,Available).

% asetetaan kenttien arvoja
set_item_value(_,[],_,_,_,[]).
set_item_value(Level,[[I,J,_]|P],I,J,N,[[I,J,N]|P]) :-
    format('at level ~w value of row ~w , col ~w set to ~w \t',[Level,I,J,N]),!.
set_item_value(Level,[[L,M,X]|P],I,J,N,[[L,M,X]| P1]) :-
    set_item_value(Level,P,I,J,N,P1).

% elementi (I,J) jonka mahdollisten arvojen joukko (Available) 
% on minimaalinen
min_dom_member(I,J,Problem,Available) :-
    member([I,J,0],Problem),
    item_values_available(Problem,I,J,Available),
    length(Available,LA),
    LA &gt; 0,
    \+((member([L,M,0],Problem),
	item_values_available(Problem,L,M,Available1),
	length(Available1,LA1),
        LA1 &gt; 0,
	LA &gt; LA1)).

% valitaan kenttä ja katsotaan että ei ole toista jolla rajoitetummin
% vaihtoehtoja jäljellä

solve(_,Solution,Solution,[]) :-
        \+member([_,_,0],Solution),
        !.

solve(Level,Problem,Solution,[[Level,I,J,Candidate]|Tasks]) :-
        min_dom_member(I,J,Problem,Available),
        !,
        member(Candidate,Available),
        set_item_value(Level,Problem,I,J,Candidate,P2),
        format(' ,when values  ~w are available.\n',[Available]),
        NextLevel is Level + 1,
        solve(NextLevel,P2,Solution,Tasks).

main1(S) :-
    initI([],1,S).

% pääpredikaatti 
% kutsu: sudoku(+Prob,+SD).
%    0&lt;= Prob  &lt;= 100
%    SD kokonaisluku, standardikokoiselle sudokulle arvoltaan 3
sudoku(Prob,SD) :-
        retractall(sudim(_)),
        assert(sudim(SD)),
        main1(S),
        format('percent  ~w \n',Prob), 
        printI(S),
        hide(S,Prob,Problem),
        printI(Problem),
        !,
        solve(1,Problem,Solution,Tasks),
        printI(Solution),
        printT(Tasks).

</pre></body></html>