Skip to content

Instantly share code, notes, and snippets.

@wvxvw
Created December 18, 2017 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wvxvw/530db8b77ab06aea108c39ec65128e94 to your computer and use it in GitHub Desktop.
Save wvxvw/530db8b77ab06aea108c39ec65128e94 to your computer and use it in GitHub Desktop.
Simple Kakuro solver in Prolog
% -*- mode: prolog -*-
:- use_module(library(clpfd)).
extract_rows([], [], X, Y) :- maplist(reverse, X, Y).
extract_rows([], Y, X, Z) :-
not(Y = []),
maplist(reverse, [Y | X], Z).
extract_rows([X | Xs], Row, Acc, Rows) :-
ground(X),
(
X = x ->
extract_rows(Xs, [], [Row | Acc], Rows)
;
extract_rows(Xs, [X], [Row | Acc], Rows)
).
extract_rows([X | Xs], Row, Acc, Rows) :-
var(X),
extract_rows(Xs, [X | Row], Acc, Rows).
normalize_row([], X, Y) :- reverse(X, Y).
normalize_row([X | Xs], Ys, Zs) :-
ground(X),
X = x/Y,
normalize_row(Xs, [Y | Ys], Zs).
normalize_row([X | Xs], Ys, Zs) :-
var(X),
normalize_row(Xs, [X | Ys], Zs).
normalize_row(X, Y) :- normalize_row(X, [], Y).
flip_hv([], Ys, Zs) :- reverse(Ys, Zs).
flip_hv([X | Xs], Ys, Zs) :-
(var(X), ! ; X = x),
flip_hv(Xs, [X | Ys], Zs).
flip_hv([X | Xs], Ys, Zs) :-
ground(X),
X = N/Y,
flip_hv(Xs, [Y/N | Ys], Zs).
flip_hv(X, Y) :- flip_hv(X, [], Y).
merge([], X, X).
merge([X | Xs], Y, Z) :-
merge(Xs, [X | Y], Z).
normalize([], X, X).
normalize([E | Es], Acc, Res) :-
(
normalize_row(E, NE) ->
normalize(Es, [NE | Acc], Res)
;
normalize(Es, Acc, Res)
).
rows([], X, X).
rows([Row | Rows], Acc, Res) :-
extract_rows(Row, [], [], Extracted),
(
normalize(Extracted, [], Normalized) ->
(
merge(Normalized, Acc, MAcc),
rows(Rows, MAcc, Res)
)
;
rows(Rows, Acc, Res)
).
solve_sum([]).
solve_sum([Sum | Summands]) :-
all_distinct(Summands),
sum(Summands, #=, Sum).
solve_sums([]).
solve_sums([X | Xs]) :- solve_sum(X), solve_sums(Xs).
solve(Board) :-
term_variables(Board, Vars),
Vars ins 1..9,
rows(Board, [], Rows),
transpose(Board, TBoard),
maplist(flip_hv, TBoard, RCols),
rows(RCols, [], Cols),
solve_sums(Rows),
solve_sums(Cols),
label(Vars).
board([
[x , 23/x, 30/x , x , x , 27/x, 12/x, 16/x],
[x/16, A , B , x , 17/24, C , D , E ],
[x/17, F , G , 15/29, F , H , J , K ],
[x/35, L , M , N , O , P , 12/x, x ],
[x , x/7 , Q , R , 7/8 , S , T , 7/x ],
[x , 11/x, 10/16, U , V , W , X , Y ],
[x/21, Z , A1 , B1 , C1 , x/5 , D1 , E1 ],
[x/6 , F1 , G1 , H1 , x , x/3 , I1 , J1 ]
]).
kakuro :-
board(Board),
solve(Board),
format('~w~n', [Board]).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment