Moortiii icon

reading

Moortiii | PRO | 11/19/19 08:44:55 AM UTC | 0 ⭐ | 7697 👁️ | Never ⏰ | []
Prolog |

5.28 KB

|

None

|

0 👍

/

0 👎

outputFile('./neighbours_solved.txt').
inputFile('./neighbours_unsolved.txt').
 
/********************* dummy solution algorithms -> fill your correct algorithm here */
:- use_module(library(clpfd)).
 
valid_neighbors([_]).
 
% If two numbers are neighbors, they must be within +1 of each other
valid_neighbors([A, N, B|T]):-
    N #= 1,
    abs(A-B) #= 1, A #\= B,
    valid_neighbors([B|T]).
 
% If two numbers are not neighbors, they cannot be within +1 of each other
valid_neighbors([A, N, B|T]):-
    N #= 0,
    abs(A-B) #\= 1, A #\= B,
    valid_neighbors([B|T]).
 
% Numbers have to be between 1 and the size of the board
valid_numbers(Size, [H]):-
  H in 1..Size.
 
valid_numbers(Size, [H, _|T]):-
  H in 1..Size,
  valid_numbers(Size, T).
 
% Remove every other element of a list.
r([], []).
r([X], [X]).
r([X,_|Xs], [X|Ys]):- r(Xs, Ys).
 
% Use constraint propagation in order to solve boards
% Inspired by the techniques used at https://www.swi-prolog.org/pldoc/man?section=clpfd-sudoku
solve(Size, Grid):-
  % A board with size 4 needs three extra lines for the neighbor rows.
  % A board of size N needs N * 2 - 1 lines to accommodate for the neighbor rows.
  N #= Size * 2 - 1, length(Grid, N),
  maplist(same_length(Grid), Grid),
 
  % The final solution is presented without neighbor symbols
  removeNeighbors(Grid, Solution),
 
  % Transpose the grid in order to apply the same rules to the columns
  transpose(Grid, Transposed),
 
  % Every other line of the grid is a value row
  removeNeighborLines(Grid, VRows),
 
  % The rules of the neighbor relations need to be upheld for the rows
  maplist(valid_neighbors, VRows),
 
  % Every other element of the value rows are values
  maplist(r, VRows, RowValues),
 
  % Each value can only appear once on every row
  maplist(all_distinct, RowValues),
  
  % Ensure all numbers on a line are valid.
  maplist(valid_numbers(Size), VRows),
 
  % Every other row of the columns is a value column
  removeNeighborLines(Transposed, VColumns),
 
  % The rules of the neighbor relations need to be upheld for the columns
  maplist(valid_neighbors, VColumns),
 
  % Ensure all numbers on a line are valid.
  maplist(valid_numbers(Size), VColumns),
 
  % Every other element of a value column is a value
  maplist(r, VColumns, Columns),
 
  % Each value can only appear once on every column
  maplist(all_distinct, Columns),
  
  % Assign a value from the available ones to each element of the rows
  maplist(label, Solution).
 
doSolve(neighbors(size(Size),grid(Problem)),neighbors(size(Size),grid(Solution))):-
  solve(Size, Problem),
  removeNeighbors(Problem, Solution).
 
removeNeighbors([P],[S]):- removeNeighborLines(P,S).
removeNeighbors([P,_|PT],[S|ST]):- removeNeighborLines(P,S), removeNeighbors(PT,ST).
 
removeNeighborLines([P],[P]).
removeNeighborLines([P,_|PT],[P|ST]):- removeNeighborLines(PT,ST).
 
/********************* writing the result */
writeFullOutput(neighbors(size(N),grid(Grid))):- 
  write('size '), write(N), write('x'), write(N), nl, writeGrid(Grid).
 
writeGrid([]).
writeGrid([E|R]):- writeGridLine(E), writeGrid(R).
 
writeGridLine([]):- nl.
writeGridLine([E|R]):- E=0, !, write(E), write(' '), writeGridLine(R).
writeGridLine([E|R]):- write(E), write(' '), writeGridLine(R).
 
/********************** reading the input */
readProblem(neighbors(size(N),grid(Grid))):- 
  findKW(size), readInt(N), readInt(M), M=N, GridLength is N*2-1, length(Grid,GridLength), 
  readGridLines(GridLength,Grid).
 
findKW(KW):- string_codes(KW,[H|T]), peek_code(H), readKW([H|T]), !.
findKW(_):- peek_code(-1), !, fail.
findKW(KW):- get_code(_), findKW(KW).
 
readKW([]):- get_code(_).
readKW([H|T]):- get_code(H), readKW(T).
 
readGridLines(N,[A]):- length(A,N), readGridLine(A).
readGridLines(N,[A,B|T]):- length(A,N), readGridLine(A), length(B,N), readNeighborLine(B), readGridLines(N,T).
 
readGridLine([N]):- readInt(I), makeHint(I,N).
readGridLine([N,X|T]):- readInt(I), makeHint(I,N), get_code(M), translate(M,X), !, readGridLine(T).
 
readNeighborLine([X]):- get_code(M), translate(M,X), !.
readNeighborLine([X,0|T]):- get_code(M), translate(M,X), get_code(_), get_code(_), get_code(_), !, readNeighborLine(T).
 
makeHint(X,X):- X>0.
makeHint(0,_).
 
translate(-1,'ERROR: EOF').
translate(120,1).
translate(32,0).
translate(X,X).
translate(X,E):- whitespace(X), get_code(Y), translate(Y,E).
translate(X,E):- string_codes(E,[X]).
 
whitespace(10). whitespace(12). whitespace(32).
 
readInt(N):- get_code(M), handleCode(M,N).
 
handleCode(M,N):- is_number_code(M,N1), !, continueInt(N1,N).
handleCode(-1,_):- !, fail. /* EOF */
handleCode(_,N):- readInt(N).
 
continueInt(O,N):- get_code(M), is_number_code(M,M1), !, H is 10*O+M1, continueInt(H,N).
continueInt(N,N).
 
is_number_code(N, N1):- N>=48, N<58, N1 is N-48.
is_number_code(95,0).
 
/*********************** global control: starting the algorithm and the reading */
run:- inputFile(IF), see(IF), outputFile(F), tell(F), findKW(puzzles), readInt(N),  write('puzzles '), write(N), nl, solveProblems(N), told, seen, !.
run:- told, seen. /* close the files */
 
solveProblems(0).
solveProblems(N):- N>0, readProblem(P), doSolve(P, S), writeFullOutput(S), !, N1 is N-1, solveProblems(N1).
 
:- nl,nl,write(' try running "?- run."'), nl,nl,nl.
 
:- run.
:- halt.

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎