% Gegenereerd door naar-swi.py uit logiquiz.pro, niet met de hand aanpassen.
:- set_prolog_flag(double_quotes, atom).
:- style_check(-singleton).
:- dynamic domein/2, feit/1, stap/6.

% De ingebouwde predicaten van Turbo Prolog die SWI niet heeft.
str_int(S, I) :- atom_number(S, I).
clearwindow :- nl, write('<<wis>>'), nl.
readChar(_).
cursor(_, 0) :- !, nl.
cursor(_, X) :- format("~t~*|", [X]).
retract_alles :- retractall(domein(_, _)), retractall(feit(_)), retractall(stap(_, _, _, _, _, _)).

% Stappenlog: elke geplaatste plus of min, met de leidFeitenAf-clause die bezig was.
plaats(feit(eigenschap(A, B, C, D, T))) :-
    assertz(feit(eigenschap(A, B, C, D, T))),
    b_getval(regel, R),
    assertz(stap(R, A, B, C, D, T)).

lees_puzzel(File) :-
    setup_call_cleanup(open(File, read, S), lees_termen(S), close(S)).
lees_termen(S) :-
    read_term(S, T, [double_quotes(atom)]),
    ( T == end_of_file -> true ; assertz(T), lees_termen(S) ).


  splits([H|T], H, T).
  splits([H|T], X, [H|TX]) :- splits(T, X, TX).

  pos([H|_], H, 0).
  pos([_|T], X, Positie) :-
    pos(T, X, Pos),
    Positie is Pos + 1.

  kleinste([], X, X) :- !.

  kleinste([H|T], X, Antw) :-
    str_int(H, Hint),
    str_int(X, Xint),
    Hint < Xint,
    kleinste(T, H, Antw).

  kleinste([H|T], X, Antw) :-
    str_int(H, Hint),
    str_int(X, Xint),
    Hint >= Xint,
    kleinste(T, X, Antw).

  grootste([], X, X) :- !.

  grootste([H|T], X, Antw) :-
    str_int(H, Hint),
    str_int(X, Xint),
    Hint >= Xint,
    grootste(T, H, Antw).

  grootste([H|T], X, Antw) :-
    str_int(H, Hint),
    str_int(X, Xint),
    Hint < Xint,
    grootste(T, X, Antw).

  zetTeken(D1, N1, D2, N2, Teken) :-
    feit(eigenschap(D1,_,D2,_,_)),
    not(feit(eigenschap(D1, N1, D2, N2, _))),
    plaats(feit(eigenschap(D1,N1,D2,N2, Teken))),!
    .

  zetTeken(D1, N1, D2, N2, Teken) :-
    feit(eigenschap(D2,_,D1,_,_)),
    not(feit(eigenschap(D2, N2, D1, N1, _))),
    plaats(feit(eigenschap(D2,N2,D1,N1, Teken))),!
    .

  zetTeken(D1, N1, D2, N2, Teken) :-
    not(feit(eigenschap(D1, N1, D2, N2, _))),
    not(feit(eigenschap(D2, N2, D1, N1, _))),
    plaats(feit(eigenschap(D1,N1,D2,N2, Teken))),!.

  zetEigenschap(eigenschap(D1,N1, D2,N2,Teken)) :-
    !,zetTeken(D1,N1,D2,N2,Teken).

  /* Zet de minnen horizontaal */
  zetMinnen(D1, N1, D2, N2, X) :-
    domein(D1, NaamLijst),
    splits(NaamLijst, Naam, _),
    Naam \= N1,
    zetTeken(D1, Naam, D2,N2, '-'),
    X = eigenschap(D1, Naam, D2, N2, '-').

  /* Zet de minnen verticaal */
  zetMinnen(D1, N1, D2, N2, X) :-
    domein(D2, NaamLijst),
    splits(NaamLijst, Naam, _),
    Naam \= N2,
    zetTeken(D1, N1, D2,Naam, '-'),
    X = eigenschap(D1, N1, D2, Naam, '-').

  alleenMinnenH(_, [], _, _).
  alleenMinnenH(D1, [H|T], D2, N2) :-
    feit(eigenschap(D1, H, D2, N2, '-')),
    alleenMinnenH(D1, T, D2, N2),!.

  alleenMinnenV(_, _, _,[]).
  alleenMinnenV(D1, N1, D2, [H|T]) :-
    feit(eigenschap(D1, N1, D2, H, '-')),
    alleenMinnenV(D1, N1, D2, T),!.

  lijstVan(X, 0, X).
  lijstVan([_|T], Positie, R) :-
    Positie \= 0,
    Pos1 is Positie - 1,
    lijstVan(T, Pos1, R).

  lijstTot(_, 0 ,[]).
  lijstTot([H|T], Pos, [H|R]) :-
    Pos \= 0,
    Pos1 is Pos - 1,
    lijstTot(T, Pos1, R).

  alleenMinnen(_,_,_,[]).
  alleenMinnen(D1, N1, D2, [H|T]) :-
    feit(eigenschap(D1, N1, D2, H, '-')),
    alleenMinnen(D1, N1, D2, T).

  zetMinnenLijst(D1, N1, D2, Ds, O) :-
    splits(Ds, X, _),
    O = eigenschap(D1, N1, D2, X, '-'),
    zetEigenschap(O).


  rijMinnen(D1, N1, D2, N2, O) :-
    domein(D1, NaamLijst),
    splits(NaamLijst, N1, Lijst), /* Op D1, N1, D3, N2 staat toch al een min */
    splits(Lijst, Onbekend, MLijst),
    O = eigenschap(D1, Onbekend, D2, N2, '+'),
    not(feit(eigenschap(D1, Onbekend, D2, N2, _))),/* Er is een feit nog niet
  bekend */
    alleenMinnenH(D1, MLijst, D2, N2).

  rijMinnen(D1, N1, D2, N2, O) :-
    domein(D2, NaamLijst),
    splits(NaamLijst, N2, Lijst), /* Op D1, N1, D2, N2 staat toch al een min */
    splits(Lijst, Onbekend, MLijst),
    O = eigenschap(D1, N1, D2, Onbekend, '+'),
    not(feit(eigenschap(D1, N1, D2, Onbekend, _))), /* Er is een feit nog niet
  bekend */
    alleenMinnenV(D1, N1, D2, MLijst).

  spiegel(D1, N1, D2, N2, O) :-
    feit(eigenschap(D3, N3, D1, N1, Teken)),
    D3 \= D2,
    O = eigenschap(D3, N3, D2, N2, Teken).

  spiegel(D1, N1, D2, N2, O) :-
    feit(eigenschap(D1, N1, D3, N3, Teken)),
    D3 \= D2,
    O = eigenschap(D3, N3, D2, N2, Teken).

  spiegel(D1, N1, D2, N2, O) :-
    feit(eigenschap(D3, N3,D2,N2,Teken)),
    D3 \= D1,
    O = eigenschap(D3, N3, D1, N1, Teken).

  spiegel(D1, N1, D2, N2, O) :-
    feit(eigenschap(D2,N2,D3, N3, Teken)),
    D3 \= D1,
    O = eigenschap(D3, N3, D1, N1, Teken).

  leidVerschilAf(Lijst, Verschil, R) :-
    splits(Lijst, X, RestLijst),
    splits(RestLijst, Y, _),
    str_int(X, Xint),
    str_int(Y, Yint),
    Yint =:= Xint + Verschil,
    R = stringtupel(X,Y).

  splitsLijst([], [], []).
  splitsLijst([stringtupel(X,Y)|T], [X|Tl1], [Y|Tl2]) :-
    splitsLijst(T, Tl1, Tl2).

  omgekeerdMin(D1, N1, D2, Lijst, Min) :-
    domein(D2, Ds),
    splits(Ds, Naam,_),
    not(splits(Lijst, Naam, _)),
    Min = eigenschap(D1, N1, D2, Naam, '-'),
    zetEigenschap(Min).

  ongelijk(D1,_,D1,_).
  ongelijk(D1,N1,D2,N2) :-
    D1 \= D2,
    zetTeken(D1, N1, D2, N2, '-'),
    leidFeitenAf([eigenschap(D1,N1,D2,N2, '-')]).

  ongelijk(_,_,_,_).

  wissel(D1,N1,D2,N2,D1,N1,D2,N2).
  wissel(D1,N1,D2,N2,D2,N2,D1,N1).

  leidFeitenAf([]).

  /* Als er een plus voorkomt kunnen er minnen gezet worden */
  leidFeitenAf([eigenschap(D1,N1,D2,N2,'+')|_]) :-
    b_setval(regel, 1),
    findall(X, zetMinnen(D1,N1,D2,N2,X), Y),
    leidFeitenAf(Y),
    fail.

  /* Als er een plus gezet is kan er gespiegeld worden */
  leidFeitenAf([eigenschap(D1, N1, D2, N2, '+') | _]) :-
    b_setval(regel, 2),
    spiegel(D1, N1, D2, N2, O),
    zetEigenschap(O),
    leidFeitenAf([O]),
    fail.

  /* Zoek naar een rij minnen, zodat er een plus gezet kan worden */
  leidFeitenAf([eigenschap(D1,N1,D2,N2,'-')|_]) :-
    b_setval(regel, 3),
    rijMinnen(D1, N1, D2, N2, Plus),
    zetEigenschap(Plus),
    leidFeitenAf([Plus]),
    fail.

  /* Voor groter dan */
  leidFeitenAf([eigenschap(P1,Q1,P2,Q2,'-')|_]) :-
    b_setval(regel, 4),
    wissel(P1,Q1,P2,Q2,D1,N1,D2,N2),
    feit(groter(D1, D3, D2, N1, N3)),
    domein(D2, Ds),
    pos(Ds, N2, Positie),
    lijstVan(Ds, Positie, MinLijst),
    alleenMinnen(D1,N1,D2,MinLijst),
    Pos1 is Positie - 1,
    pos(Ds, ElemVerder, Pos1),
    findall(X, zetMinnenLijst(D3,N3,D2, [ElemVerder|MinLijst], X), Y),
    leidFeitenAf(Y),
    fail.

  leidFeitenAf([eigenschap(P1,Q1,P2,Q2,'-')|_]) :-
    b_setval(regel, 5),
    wissel(P1,Q1,P2,Q2,D1,N1,D2,N2),
    feit(groter(D3, D1, D2, N3, N1)),
    domein(D2, Ds),
    pos(Ds, N2, Positie),
    lijstTot(Ds, Positie, MinLijst),

    alleenMinnen(D1, N1,D2, MinLijst),
    Pos1 is Positie + 1,
    pos(Ds, ElemVerder, Pos1),
    findall(X, zetMinnenLijst(D3, N3,D2, [ElemVerder|MinLijst], X), Y),
    leidFeitenAf(Y),
    fail.

  /* Verschil */
  leidFeitenAf([eigenschap(P1,Q1,P2,Q2,Teken)|_]) :-
    b_setval(regel, 6),
    wissel(P1,Q1,P2,Q2,D1,N1,D2,N2),
    feit(verschil(D1, D3, D2, N1, N3, Aantal)),
    str_int(N2, N2int),
    Waarde is N2int + Aantal,
    str_int(WaardeString, Waarde),
    domein(D2, Ds),
    splits(Ds, WaardeString, _),
    NE = eigenschap(D3, N3, D2, WaardeString, Teken),
    zetEigenschap(NE),
    leidFeitenAf([NE]),
    fail.

  leidFeitenAf([eigenschap(P1,Q1,P2,Q2,Teken)|_]) :-
    b_setval(regel, 7),
    wissel(P1,Q1,P2,Q2,D1,N1,D2,N2),
    feit(verschil(D3, D1, D2, N3, N1, Aantal)),
    str_int(N2, N2int),
    Waarde is N2int - Aantal,
    str_int(WaardeString, Waarde),
    domein(D2, Ds),
    splits(Ds, WaardeString, _),
    NE = eigenschap(D3, N3, D2, WaardeString, Teken),
    zetEigenschap(NE),
    leidFeitenAf([NE]),
    fail.


  leidFeitenAf([verschil(D1, D2, D3, N1, N2, Aantal) |_]) :-
    b_setval(regel, 8),
    domein(D3, X),
    findall(Paar, leidVerschilAf(X, Aantal,Paar),PaarLijst),
    ongelijk(D1, N1, D2, N2),
    splitsLijst(PaarLijst, Lijst1, Lijst2),
    findall(Min,omgekeerdMin(D1, N1, D3, Lijst1, Min), Minnen1),
    findall(Min,omgekeerdMin(D2, N2, D3, Lijst2, Min), Minnen2),

    leidFeitenAf(Minnen1),
    leidFeitenAf(Minnen2), fail.

  leidFeitenAf([groter(D1, D2, D3, N1, N2) |_]) :-
    b_setval(regel, 9),
    domein(D3, [H|Ds]),
    kleinste(Ds, H, X),
    ongelijk(D1, N1,D2, N2),
    NE = eigenschap(D1,N1, D3, X, '-'),
    zetEigenschap(NE),
    leidFeitenAf([NE]), fail.

  leidFeitenAf([groter(_, D2, D3, _, N2) |_]) :-
    b_setval(regel, 10),
    domein(D3, [H|Ds]),
    grootste(Ds, H, X),
    NE = eigenschap(D2, N2, D3, X, '-'),
    zetEigenschap(NE),
    leidFeitenAf([NE]), fail.

  leidFeitenAf([_|T]) :-
    write('#'),
    leidFeitenAf(T).

  maakLogi(File) :-
    retract_alles,
    write("Een moment a.u.b. "),nl,
    lees_puzzel(File), !,
    findall(X, feit(X), Y),
    leidFeitenAf(Y), show
    .

/* Display gedeelte */


  writeList(_,_,_,_,[]).
  writeList(X,Y,Domein, Naam, [H|T]) :-
    feit(eigenschap(Domein, Naam, H, Inhoud, '+')),
    cursor(Y,X),
    write(Inhoud),
    X1 is X + 22,
    writeList(X1,Y,Domein, Naam, T),!.

  writeList(X,Y,Domein, Naam, [H|T]) :-
    feit(eigenschap(H, Inhoud,Domein, Naam,'+')),
    cursor(Y,X),
    X1 is X + 22,
    write(Inhoud),
    writeList(X1, Y, Domein, Naam, T),!.

  writeNamen(_,_,_,[]).
  writeNamen(Y,Domein,DList,[H|T]) :-
    cursor(Y,0),
    write(H),
    writeList(10,Y, Domein, H, DList), !,
    Y1 is Y + 1,
    writeNamen(Y1,Domein, DList,T).

  show :-
    clearwindow,
    write("+-----------------------------------------------------------------------"),nl,
    write(" Logiquiz oplosser                                       november 1997 "),nl,
    write("                                                                      "),nl,
    write(" Auteur: Raymond van Dongelen                                         "),nl,
    write("------------------------------------------------------------------------"),nl,
    nl,
    domein(D,NList),
    findall(X, domein(X,_), OudeDList),
    splits(OudeDList, D, DList),
    !,
    writeNamen(7,D, DList, NList),
    nl,
    nl,
    readChar(_).
