view 3-Prolog/day3-sudoku.pl @ 66:2acc1ad8d365

Add half-completed sudoku solver
author IBBoard <dev@ibboard.co.uk>
date Mon, 02 Oct 2017 21:02:22 +0100
parents
children 8906b5a4517f
line wrap: on
line source

% Create a generic sudoku reader

valid([]).
valid([Head|Tail]) :-
    fd_all_different(Head),
    valid(Tail).

sudoku(Board, X, Y, Solution) :-
    Solution = Board,
    Max is X * Y,
    fd_domain(Solution, 1, Max),
    board(X, Y, Board),
    rows(Board, Max, Rows),
    cols(Board, Max, Cols),
    valid(Rows),
    valid(Cols).
% TODO: Calculate boxes and validate them

board(X, Y, Board) :-
    Size is X * Y * X * Y,
    board(Size, Board).
board(1, [_]).
board(Size, [_|Board]) :- SmallerSize is Size - 1, board(SmallerSize, Board).

sublist(Start, Length, Input, Output) :- End is Start + Length - 1, sublist(Start, End, 1, Input, Output).
sublist(Start, End, Pos, [Head|TailIn], [Head|TailOut]) :- Pos >= Start, Pos =< End, NextPos is Pos + 1, sublist(Start, End, NextPos, TailIn, TailOut).
sublist(Start, End, Pos, [_|TailIn], Output) :- Pos < Start, NextPos is Pos + 1, sublist(Start, End, NextPos, TailIn, Output).
sublist(_, End, Pos, _, []) :- Pos > End.

rows(Board, RowLength, Rows) :- rows(Board, RowLength, 1, Rows).
rows(Board, RowLength, RowNum, [NewRow|Rows]) :- RowNum =< RowLength, NextRowNum is RowNum + 1,
    Start is ((RowNum - 1) * RowLength) + 1, sublist(Start, RowLength, Board, NewRow),
    rows(Board, RowLength, NextRowNum, Rows).
rows(_, RowLength, RowNum, []) :- RowNum > RowLength.

nth_from_list(Start, N, Input, Output) :- nth_from_list(N, Start, 1, Input, Output).
nth_from_list(N, Next, Pos, [Head|TailIn], [Head|TailOut]) :- Pos == Next, NewNext is Next + N, NewPos is Pos + 1,
    nth_from_list(N, NewNext, NewPos, TailIn, TailOut).
nth_from_list(N, Next, Pos, [_|TailIn], Output) :- NewPos is Pos + 1, nth_from_list(N, Next, NewPos, TailIn, Output).
nth_from_list(_, _, _, [], []).

cols(Board, ColLength, Cols) :- cols(Board, ColLength, 1, Cols).
cols(Board, ColLength, ColNum, [NewCol|Cols]) :- ColNum =< ColLength, NextColNum is ColNum + 1,
    nth_from_list(ColNum, ColLength, Board, NewCol),
    cols(Board, ColLength, NextColNum, Cols).
cols(_, ColLength, ColNum, []) :- ColNum > ColLength.