Skip to content

Instantly share code, notes, and snippets.

@scintill
Last active July 10, 2018 10:08
Show Gist options
  • Save scintill/4e888e3330963996329fbeded81e4b56 to your computer and use it in GitHub Desktop.
Save scintill/4e888e3330963996329fbeded81e4b56 to your computer and use it in GitHub Desktop.
Puzzle solver in Prolog
% match head and tail, left/right, top/bottom
partsMatch(top(Type), bottom(Type)).
partsMatch(bottom(Type), top(Type)).
cardsMatch(card(_, Right, _, _), right, card(_, _, _, Left)) :- partsMatch(Right, Left).
cardsMatch(card(_, _, Bottom, _), down, card(Top, _, _, _)) :- partsMatch(Bottom, Top).
% define card rotation
rotate(card(A, B, C, D), 0, R) :- R = card(A, B, C, D).
rotate(card(A, B, C, D), 1, R) :- R = card(B, C, D, A).
rotate(card(A, B, C, D), 2, R) :- R = card(C, D, A, B).
rotate(card(A, B, C, D), 3, R) :- R = card(D, A, B, C).
% card rotating/matching with XY coords
cardsMatchXY(Cards, CardRotations, X1, Y1, Direction) :-
nextCoord(X1, Y1, Direction, X2, Y2),
foldl(nth0, [Y1, X1], Cards, CardA),
foldl(nth0, [Y2, X2], Cards, CardB),
foldl(nth0, [Y1, X1], CardRotations, CardARI),
foldl(nth0, [Y2, X2], CardRotations, CardBRI),
rotate(CardA, CardARI, CardAR),
rotate(CardB, CardBRI, CardBR),
cardsMatch(CardAR, Direction, CardBR).
nextCoord(X, Y, right, XR, YR) :- XR is X+1, YR is Y.
nextCoord(X, Y, down, XR, YR) :- YR is Y+1, XR is X.
% Match the 3x3 square of cards, yielding the rotated grid that solves them.
% solved(-CardsRotated)
solved(CardsRotated) :-
permutation(CardsFlat, [
card(top(spotted), top(tabby), top(persian), bottom(siamese)),
card(top(persian), top(siamese), bottom(tabby), bottom(siamese)),
card(top(persian), bottom(tabby), bottom(spotted), top(siamese)),
card(bottom(spotted), bottom(tabby), top(persian), top(siamese)),
card(top(siamese), top(spotted), bottom(spotted), top(tabby)),
card(top(spotted), bottom(siamese), bottom(persian), top(tabby)),
card(bottom(tabby), bottom(siamese), bottom(persian), bottom(spotted)),
card(bottom(persian), bottom(tabby), top(spotted), top(persian)),
card(top(spotted), bottom(tabby), top(persian), top(siamese))
]),
% TODO remove assumptions and repetitions of board size
maplist(length, Cards, [3,3,3]),
maplist(length, CardRotations, [3,3,3]),
flatten(Cards, CardsFlat),
% TODO make this more idiomatic, less repetitive - look at https://github.com/Anniepoo/prolog-examples/blob/master/children.pl
cardsMatchXY(Cards, CardRotations, 0, 0, right),
cardsMatchXY(Cards, CardRotations, 1, 0, right),
cardsMatchXY(Cards, CardRotations, 0, 1, right),
cardsMatchXY(Cards, CardRotations, 1, 1, right),
cardsMatchXY(Cards, CardRotations, 0, 2, right),
cardsMatchXY(Cards, CardRotations, 1, 2, right),
cardsMatchXY(Cards, CardRotations, 0, 0, down),
cardsMatchXY(Cards, CardRotations, 0, 1, down),
cardsMatchXY(Cards, CardRotations, 1, 0, down),
cardsMatchXY(Cards, CardRotations, 1, 1, down),
cardsMatchXY(Cards, CardRotations, 2, 0, down),
cardsMatchXY(Cards, CardRotations, 2, 1, down),
flatten(CardRotations, CardRotationsFlat),
maplist(rotate, CardsFlat, CardRotationsFlat, CardsRotatedFlat),
maplist(length, CardsRotated, [3,3,3]),
flatten(CardsRotated, CardsRotatedFlat).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment