Reputation: 103
I'm attempting to implement a Skyscraper puzzle solver in Prolog, using constraints (CLPFD).
I've realized a great constraint would be calculating the number of times the maximum switches whilst traversing each row and column and matching it with the side clue.
Here's an example of a single row:
*2* [ _ | _ | _ | _ ] *3* -> *2* [ 1 | 4 | 3 | 2 ] *3*
The list [1, 4, 3, 2]
works for clue 2 because it has 2 maximum switches (0 -> 1 -> 4).
It also works for clue 3 because the same list reversed - [2, 3, 4, 1]
- has 3 maximum switches (0 -> 2 -> 3 -> 4).
I've managed to program a predicate that returns me the number of maximum switches of a list.
The issue is how to actually utilize it to generate a new constraint? I can't pass my list/matrix directly because it isn't yet initialized.
It should probably be something like:
calculate_max_switches(List, Switches),
% Generate a list whose Switches value is equal to the clue number.
Thank you.
Upvotes: 3
Views: 446
Reputation: 60004
Without seeing your code, here is my hint, adapted from my previous answer:
:- use_module(library(clpfd)).
skyscrape_row(Left, Right, Heights) :-
constraint_view(0, Heights, LHeights),
sum(LHeights, #=, Left),
reverse(Heights, Heights_),
constraint_view(0, Heights_, RHeights),
sum(RHeights, #=, Right).
constraint_view(_, [], []).
constraint_view(Top, [V|Vs], [R|Rs]) :-
R #<==> V #> 0 #/\ V #> Top,
Max #= max(Top, V),
constraint_view(Max, Vs, Rs).
that applied to your example yields
?- L=[A,B,C,D], L ins 1..4, all_different(L), skyscrape_row(2,3,L), label(L).
A = 1,
B = 4,
C = 3,
D = 2,
L = [1, 4, 3, 2]
A = 2,
B = 4,
C = 3,
D = 1,
L = [2, 4, 3, 1]
A = 3,
B = 4,
C = 2,
D = 1,
L = [3, 4, 2, 1]
Live code is available in SWISH
Upvotes: 3