Related
I am new on prolog and I want to list the n-ary partitions of a number in prolog using backtracking. The result must be something like this:
?- nary(3,9,P).
P = [9] ? ;
P = [3,3,3] ? ;
P = [3,3,1,1,1] ? ;
P = [3,1,1,1,1,1,1] ? ;
P = [1,1,1,1,1,1,1,1,1] ? ;
no
Do you have any ideas of how to do it?
Lots of thanks.
Assuming that you mean n-ary partitions as described in Characterizing the Number of m-ary Partitions Modulo m:
... These are partitions of an integer n wherein each part is a power of a fixed integer m >= 2. ... As an example, note that there are five 3-ary partitions of n=9: 9, 3+3+3, 3+3+1+1+1, 3+1+1+1+1+1+1, 1+1+1+1+1+1+1+1+1. ...
Note, that in the linked Paper the m corresponds to the n in your question. Building on base_limit_powers/3 from this answer, I propose to keep using DCGs and CLP(FD). Let's start with a name for the predicate and the DCG, e.g. nary_partitions_of/3 (Note that I swapped the second and third arguments of your predicate nary/3 to more easily obtain a nice declarative name) and partitions_//4.
The second argument is a list (Partitions), consisting of powers of the first argument (N), that add up to the number that is the third argument (Int). The first number has to be greater or equal to 2 per definition (see above), hence the sum has to be as well. Since you want the powers in the list in descending order, the predicate reverse/2 from library(lists) can be used to reorder the list of powers as described by base_limit_powers/3 and have partitions_//4 start with the largest number. Because of N and Int being larger than 1 the list of powers is not empty and its corresponding reversed list can be written in head and tail notation ([FRP|RPs], read F irst of R eversed P owers and rest of R eversed P ower s), thereby providing easy access to the first (and largest) number (FRP) that is to be used as second argument of partitions_//4. At the time partitions_//4 is called (using phrase/2), the list Partitions is yet to be described, therefore the sum of its numbers is still 0. Putting all this together the relation nary_partitions_of/3 can be defined like so:
nary_partitions_of(N,Partitions,Int) :-
N #> 1,
Int #> 1,
base_limit_powers(N,Int,Powers),
reverse(Powers,[FRP|RPs]),
phrase(partitions_([FRP|RPs],FRP,0,Int),Partitions).
Then the n-ary partitions can be described by a DCG like so:
partitions_(_Powers,_Last,Int,Int) --> % If the sum and the integer are equal
[]. % the list is finished
partitions_(Powers,Last,Sum0,Int) --> % otherwise
{Sum0 #< Int}, % the sum is smaller than the integer and
{P #=< Last}, % the power to be added is less or equal to the last power in the partition and
{member(P,Powers)}, % the power is from the list of powers and
{Sum1 #= Sum0 + P}, % adds to the sum of powers so far and
[P], % the power is in the list of partitions and
partitions_(Powers,P,Sum1,Int). % the remainder of the partition-list is described recursively
With this definition your example query produces the desired answers:
?- nary_partitions_of(3,P,9).
P = [9] ? ;
P = [3,3,3] ? ;
P = [3,3,1,1,1] ? ;
P = [3,1,1,1,1,1,1] ? ;
P = [1,1,1,1,1,1,1,1,1] ? ;
no
Due to the use of CLP(FD) you can also use nary_partitions_of/3 to ask different types of questions, e.g. to check if a given list is a partition of some N and Int, however this query loops after producing the answers:
?- nary_partitions_of(N,[9],Int).
Int = N = 9 ? ;
Int = 9,
N = 3 ? ;
% loop here
But due to the use of CLP(FD) that can be remedied by constraining the range of N like so:
?- N in 2..5, nary_partitions_of(N,[9],Int).
Int = 9,
N = 3 ? ;
no
?- N in 2..5, nary_partitions_of(N,[3,3,3],Int).
Int = 9,
N = 3 ? ;
no
?- N in 2..5, nary_partitions_of(N,[3,3,1,1,1],Int).
Int = 9,
N = 3 ? ;
no
?- N in 2..5, nary_partitions_of(N,[3,3,1,1],Int).
Int = 8,
N = 3 ? ;
no
?- N in 2..5, nary_partitions_of(N,[3,3,4],Int).
no
You can also look for n-ary partitions of some number, e.g. 9 without specifying N:
?- N in 2..6, nary_partitions_of(N,P,9).
N = 4,
P = [4,4,1] ? ;
N = 6,
P = [6,1,1,1] ? ;
N = 5,
P = [5,1,1,1,1] ? ;
N = 4,
P = [4,1,1,1,1,1] ? ;
P = [1,1,1,1,1,1,1,1,1],
N in 3..6, % residual goal
N^2#=_A, % residual goal
_A in 10..36 ? ; % residual goal
.
.
.
However this leads to some residual goals in the answers (see CLP(FD) documentation for details). You can again remedy this by constraining N, this time also labeling it:
?- N in 2..6, nary_partitions_of(N,P,9), label([N]).
N = 4,
P = [4,4,1] ? ;
N = 6,
P = [6,1,1,1] ? ;
N = 5,
P = [5,1,1,1,1] ? ;
N = 4,
P = [4,1,1,1,1,1] ? ;
N = 4,
P = [1,1,1,1,1,1,1,1,1] ? ;
N = 5,
P = [1,1,1,1,1,1,1,1,1] ? ;
N = 6,
P = [1,1,1,1,1,1,1,1,1] ? ;
N = 3,
P = [9] ? ;
N = 3,
P = [3,3,3] ? ;
N = 3,
P = [3,3,1,1,1] ? ;
N = 3,
P = [3,1,1,1,1,1,1] ? ;
N = 3,
P = [1,1,1,1,1,1,1,1,1] ? ;
N = 2,
P = [8,1] ? ;
N = 2,
P = [4,4,1] ? ;
N = 2,
P = [4,2,2,1] ? ;
N = 2,
P = [4,2,1,1,1] ? ;
N = 2,
P = [4,1,1,1,1,1] ? ;
N = 2,
P = [2,2,2,2,1] ? ;
N = 2,
P = [2,2,2,1,1,1] ? ;
N = 2,
P = [2,2,1,1,1,1,1] ? ;
N = 2,
P = [2,1,1,1,1,1,1,1] ? ;
N = 2,
P = [1,1,1,1,1,1,1,1,1] ? ;
no
I came up with this, where the nary partitions are either the number in a list, or it expanded (spand). Then the spand process takes the first number evenly divisible by the partition size, splits the list on it, inserts the partition, and either completes there OR spands the newly constructed complete list on backtracking.
This was about the only way I could get your backtracking request without the backtracking undoing the previous expansion and turning 1,1,1 back into 3. I haven't been able to split the list on the first evenly divisible element without leaving any choicepoints in a nicer way, but there probably is a nicer way.
spand(In, Psize, Out) :-
once((append(Left, [Elem|Right], In), % first divisible element, e.g. 3
0 is Elem mod Psize)),
length(Parts, Psize), % make the partition list, e.g. [1,1,1]
Pt is Elem / Psize,
maplist(=(Pt), Parts),
append(Left, Parts, Temp),
( append(Temp, Right, Out) % choicepoint for backtracking
; append(Temp, Right, Out_),
spand(Out_, Psize, Out)).
nary(Psize, Target, Parts) :-
Parts = [Target]
;
spand([Target], Psize, Parts).
e.g.
?- nary(3, 9, Parts).
Parts = [9] ;
Parts = [3, 3, 3] ;
Parts = [1, 1, 1, 3, 3] ;
Parts = [1, 1, 1, 1, 1, 1, 3] ;
Parts = [1, 1, 1, 1, 1, 1, 1, 1, 1] ;
false
e.g.
?- nary(2, 24, Parts).
Parts = [24] ;
Parts = [12, 12] ;
Parts = [6, 6, 12] ;
Parts = [3, 3, 6, 12] ;
Parts = [3, 3, 3, 3, 12] ;
Parts = [3, 3, 3, 3, 6, 6] ;
Parts = [3, 3, 3, 3, 3, 3, 6] ;
Parts = [3, 3, 3, 3, 3, 3, 3, 3] ;
false
Your example is too short to see if [6, 6, 12] -> [3, 3, 6, 12] or [6, 6, 6, 6]. Depth first or Breadth first.
Before our Prolog final exam soon, I got some practice questions and I am stuck on one:
For each integer n > 0,
let Ln := {s ∈ {0, 1}+ | s ends in a string from 1(0 + 1)n−1}
be the set of bit-strings whose n-th to the last bit is 1. That is, Ln is described by the regular expression (0 + 1)∗1(0 + 1)n−1.
Define a DCG for the 3-ary predicate s/3 such that s(n,s,[]) is true exactly if s encodes a string in Ln.
I tried for a while to get this, but I am unsure what to do, does anyone have a solution?
Here's a DCG for (0 + 1)*:
zero_or_one -->
[0].
zero_or_one -->
[1].
many_zero_or_one -->
[].
many_zero_or_one -->
zero_or_one,
many_zero_or_one.
Let's try to make it look like the regular expression you showed, just for funzies. I will not define operators and instead "parse" the regex to something that Prolog can read without new operator definitions (I am not even sure if you can make it work just with redefining operators, maybe it isn't possible). So I will define a +//2 for "or" and *//1 for "0 or more repetitions" and n//2 for "n repetitions".
+(A, B) --> [A] | [B].
*(P) --> [] | call(P), *(P).
n(P, N) --> { length(L, N) }, n_1(L, P).
n_1([], _) --> [].
n_1([_|L], P) --> call(P), n_1(L, P).
With those available I can write a query that roughly resembles your problem statement:
?- length(L, _), phrase(( *(+(0,1)), [1], n(+(0,1), 1) ), L).
L = [1, 0] ;
L = [1, 1] ;
L = [0, 1, 0] ;
L = [0, 1, 1] ;
L = [1, 1, 0] ;
L = [1, 1, 1] ;
L = [0, 0, 1, 0] ;
L = [0, 0, 1, 1] ;
L = [0, 1, 1, 0] . % it goes on
Note that here I set the n to be equal to 2, so in n//2 I am using 2 - 1 = 1.
EDIT: I noticed that the *//1 I defined is just a special case of n//2. So you can actually do this:
?- phrase(n(+(0,1), N), L).
N = 0,
L = [] ;
N = 1,
L = [0] ;
N = 1,
L = [1] ;
N = 2,
L = [0, 0] ;
N = 2,
L = [0, 1] ;
N = 2,
L = [1, 0] ;
N = 2,
L = [1, 1] ;
N = 3,
L = [0, 0, 0] .
In other words, you can leave the N argument a free variable and you will get strings of increasing length, with the length in N.
I do not find a Prolog cut in Dijsktras "if fi", since he says "otherwise an arbitrary guarded list with a true guard will be selected for execution.". So his construct, does not choose the first match, as a Prolog cut would do:
if Cond1 -> Action11, .., Action1n1
[] Cond2 -> Action21, .., Action2n2
...
[] Condm -> Actionm1, .., Actionmn2
if
Is there maybe a Prolog cut in the "do od" construct, which loops as long as at least one condition of a guarded list is true? Or maybe some other approach to realize it in Prolog, I assume a loop can be translated to a recursive call. So how would we do this sorting of q1,q2,q3,q4 in Prolog:
do q1 > q2 -> q1,q2 := q2,q1
[] q2 > q3 -> q2,q3 := q3,q2
[] q3 > q4 -> q3,q4 := q4,q3
od
How many non-deterministic execution paths aka Prolog solutions will the Prolog program have for input 7,11,5,3 that all provide the same answer?
I think you can do something like this:
do([Q1,Q2,Q3,Q4], [swap(Q1,Q2)|P], S) :-
Q1 > Q2,
do([Q2,Q1,Q3,Q4], P, S).
do([Q1,Q2,Q3,Q4], [swap(Q2,Q3)|P], S) :-
Q2 > Q3,
do([Q1,Q3,Q2,Q4], P, S).
do([Q1,Q2,Q3,Q4], [swap(Q3,Q4)|P], S) :-
Q3 > Q4,
do([Q1,Q2,Q4,Q3], P, S).
do([Q1,Q2,Q3,Q4], [], [Q1,Q2,Q3,Q4]) :- % termination state
Q1 =< Q2,
Q2 =< Q3,
Q3 =< Q4.
Execution:
?- do([7,11,5,3],P,S).
P = [swap(11, 5), swap(7, 5), swap(11, 3), swap(7, 3), swap(5, 3)],
S = [3, 5, 7, 11] ;
P = [swap(11, 5), swap(11, 3), swap(7, 5), swap(7, 3), swap(5, 3)],
S = [3, 5, 7, 11] ;
P = [swap(11, 5), swap(11, 3), swap(5, 3), swap(7, 3), swap(7, 5)],
S = [3, 5, 7, 11] ;
P = [swap(5, 3), swap(11, 3), swap(7, 3), swap(11, 5), swap(7, 5)],
S = [3, 5, 7, 11] ;
P = [swap(5, 3), swap(11, 3), swap(11, 5), swap(7, 3), swap(7, 5)],
S = [3, 5, 7, 11] ;
false.
If we assume no guard calculation can diverge, I think the following expresses the same computation as the sort example from the question:
dgsort([A,B,C,D],R):-
( A > B -> X1 = [1] ; X1 = [] ),
( B > C -> X2 = [2|X1] ; X2 = X1 ),
( C > D -> X3 = [3|X2] ; X3 = X2 ),
( X3 = [] -> R = [A,B,C,D]
; random_member( X, X3),
( X =:= 1 -> dgsort([B,A,C,D],R)
; X =:= 2 -> dgsort([A,C,B,D],R)
; X =:= 3 -> dgsort([A,B,D,C],R) )).
comments: "an arbitrary guarded list with a true guard will be selected for execution" and all the others dropped, i.e. the chosen one is committed to, I always thought. Thus if I had to implement it I'd spawn all the branches's guards, check on them at some timeout intervals, and as soon as one or more are successful I'd pick one of them randomly, kill all the rest, and proceeded with the winner. i.e. committing to it. that is my understanding anyway. (or maybe the timeout should be random as well?)
I also thought the do-od construct chose the true guard by the same mechanism. i.e. "at least one" and we don't care which. If we assume all the guards calculations terminate, we can just execute all of them, pick the winner randomly, then proceed with its actions. Which is what the code above is doing.
To find out the number of execution paths we need to change random_member to just member, run the predicate through findall and measure the length of the resulting list:
dgsortn([A,B,C,D],R):-
( A > B -> X1 = [1] ; X1 = [] ),
( B > C -> X2 = [2|X1] ; X2 = X1 ),
( C > D -> X3 = [3|X2] ; X3 = X2 ),
( X3 = [] -> R = [A,B,C,D]
; member( X, X3),
( X =:= 1 -> dgsortn([B,A,C,D],R)
; X =:= 2 -> dgsortn([A,C,B,D],R)
; X =:= 3 -> dgsortn([A,B,D,C],R) )).
Running it succeeds 5 times:
9 ?- dgsortn( [7,11,5,3], R).
R = [3, 5, 7, 11] ;
R = [3, 5, 7, 11] ;
R = [3, 5, 7, 11] ;
R = [3, 5, 7, 11] ;
R = [3, 5, 7, 11].
We could also add a counter to see the number of steps taken to produce each solution.
I directly takled the counting problem and came up with this solution. It has the defect that the negation as failure will re-evaluate the conditions.
sortloop([Q1,Q2,Q3,Q4], R) :- Q1 > Q2, sortloop([Q2,Q1,Q3,Q4], R).
sortloop([Q1,Q2,Q3,Q4], R) :- Q2 > Q3, sortloop([Q1,Q3,Q2,Q4], R).
sortloop([Q1,Q2,Q3,Q4], R) :- Q3 > Q4, sortloop([Q1,Q2,Q4,Q3], R).
sortloop([Q1,Q2,Q3,Q4], [Q1,Q2,Q3,Q4]) :- \+ Q1 > Q2, \+ Q2 > Q3, \+ Q3 > Q4.
But it shows there are 5 execution paths:
?- sortloop([7,11,5,3], R).
R = [3, 5, 7, 11] ;
R = [3, 5, 7, 11] ;
R = [3, 5, 7, 11] ;
R = [3, 5, 7, 11] ;
R = [3, 5, 7, 11] ;
false.
But can we improve that the conditions are only evaluated once? What came to my mind was the soft cut (*->)/2 since the action lists do not abort:
sortloop2([Q1,Q2,Q3,Q4], R) :-
((Q1 > Q2, sortloop2([Q2,Q1,Q3,Q4], R);
Q2 > Q3, sortloop2([Q1,Q3,Q2,Q4], R);
Q3 > Q4, sortloop2([Q1,Q2,Q4,Q3], R)) *-> true; R=[Q1,Q2,Q3,Q4]).
The soft cut solution gives the same result:
?- sortloop2([7,11,5,3], R).
R = [3, 5, 7, 11] ;
R = [3, 5, 7, 11] ;
R = [3, 5, 7, 11] ;
R = [3, 5, 7, 11] ;
R = [3, 5, 7, 11] ;
false.
But none of the solutions uses a Prolog cut that would replace the arrow between condition and action list in the Dijkstra guards. Situation is a little bit more complicated.
Edit 12.02.2021:
In case somebody is currious how the 5 paths look like as a DAG:
Eg:
List[1,2,3,4,5,6] with N equal to 6 should print true because there are exactly 3 values that add upto 6. 1+2+3.
List[2,5,7,9] with N equal to 12 should print false as there are no 3 elements that add upto 12.
Let's maybe start with a more general predicate that describes the relation between a list, a sublist of said list and the sum of numbers in the sublist. To make it obvious which argument is what, it is opportune to chose a descriptive name for the predicate, say sum_ofsub_fromlist/3. Now let's observe that if the first argument is the sum of the numbers in the sublist, then successively subtracting those numbers from the sum yields zero, e.g.: X=A+B → X-A-B=0. So there will be a base case that contains 0 as the sum and [] as the sublist (rule 1) and a recursive rule that subtracts the elements of the sublist from the sum (rule 2). And since a sublist does not contain all elements of the list it's taken from in general, there will be a recursive rule for skipping elements of the list that do not occur in the sublist (rule 3). This rule is only needed as long as there are still elements in the sublist, so a constraint would be beneficial, that prevents this rule from succeeding once the sublist is empty. These ideas can be realized in Prolog like so:
sum_ofsub_fromlist(0,[],_L). % rule 1
sum_ofsub_fromlist(X,[A|Bs],[A|As]) :- % rule 2
X0 is X-A,
sum_ofsub_fromlist(X0,Bs,As).
sum_ofsub_fromlist(X,Bs,[_A|As]) :- % rule 3
dif(Bs,[]), % constraint: sublist not empty
sum_ofsub_fromlist(X,Bs,As).
You can query this predicate to assure yourself that it delivers all sublists for the given sum in your examples:
?- sum_ofsub_fromlist(6,S,[1,2,3,4,5,6]).
S = [1, 2, 3] ;
S = [1, 5] ;
S = [2, 4] ;
S = [6] ;
false.
?- sum_ofsub_fromlist(12,S,[2,5,7,9]).
S = [5, 7] ;
false.
Building on this you can then write a calling predicate that only succeeds for sublists of length three:
sum_oftriple_fromlist(S,T,L) :-
T=[_,_,_], % T has to be a triple
sum_ofsub_fromlist(S,T,L).
This predicate yields the answers you desire:
?- sum_oftriple_fromlist(6,T,[1,2,3,4,5,6]).
T = [1, 2, 3] ;
false.
?- sum_oftriple_fromlist(12,T,[2,5,7,9]).
false.
Note that the predicate is also working with negative numbers:
?- sum_oftriple_fromlist(6,T,[-5,-3,-1,2,4,7,8,9]).
T = [-5, 2, 9] ;
T = [-5, 4, 7] ;
T = [-3, 2, 7] ;
false.
?- sum_oftriple_fromlist(-6,T,[-6,-5,-4,-3,-2,-1,2,4]).
T = [-6, -4, 4] ;
T = [-6, -2, 2] ;
T = [-5, -3, 2] ;
T = [-3, -2, -1] ;
false.
However, due to the use of is/2, the predicate only works if the first and the third arguments are ground:
?- sum_oftriple_fromlist(S,T,[1,2,3,4,5,6]).
ERROR: is/2: Arguments are not sufficiently instantiated
Exception: (7) sum_ofsub_fromlist(_G918, [_G1016, _G1019, _G1022], [1, 2, 3, 4, 5, 6]) ?
?- sum_oftriple_fromlist(6,T,[A,B,C,D,E,F]).
ERROR: is/2: Arguments are not sufficiently instantiated
Exception: (7) sum_ofsub_fromlist(6, [_G2121, _G2124, _G2127], [_G1945, _G1948, _G1951, _G1954, _G1957, _G1960]) ?
If that's fine with you, you can stop here. Alternatively, you could opt to make the predicate more versatile by using CLP(FD). Just apply these minor changes to your code:
:- use_module(library(clpfd)). % <- new
sum_oftriple_fromlist(S,T,L) :-
T=[_,_,_],
sum_ofsub_fromlist(S,T,L).
sum_ofsub_fromlist(0,[],_L).
sum_ofsub_fromlist(X,[A|Bs],[A|As]) :-
X0 #= X-A, % <- change
sum_ofsub_fromlist(X0,Bs,As).
sum_ofsub_fromlist(X,Bs,[_A|As]) :-
dif(Bs,[]),
sum_ofsub_fromlist(X,Bs,As).
Now the above queries deliver answers:
?- sum_oftriple_fromlist(S,T,[1,2,3,4,5,6]).
S = 6,
T = [1, 2, 3] ;
S = 7,
T = [1, 2, 4] ;
S = 8,
T = [1, 2, 5] ;
. % another
. % seventeen
. % results here
The second query, however, yields residual goals (see documentation for details) as results:
?- sum_oftriple_fromlist(6,T,[A,B,C,D,E,F]).
T = [A, B, C],
_G2424+A#=6,
C+B#=_G2424 ;
T = [A, B, D],
_G2424+A#=6,
D+B#=_G2424 ;
.
.
.
To get actual numbers, you have to restrict the range of the numbers and subsequently label the variables in the list:
?- L=[A,B,C,D,E,F], sum_oftriple_fromlist(6,T,L), L ins 1..6, label(L).
L = [1, 1, 4, 1, 1, 1],
A = B, B = D, D = E, E = F, F = 1,
C = 4,
T = [1, 1, 4] ;
L = [1, 1, 4, 1, 1, 2],
A = B, B = D, D = E, E = 1,
C = 4,
F = 2,
T = [1, 1, 4] ;
.
.
.
Possibly you are only interested in lists where every number only appears once:
?- L=[A,B,C,D,E,F], all_distinct(L), sum_oftriple_fromlist(6,T,L), L ins 1..6, label(L).
L = [1, 2, 3, 4, 5, 6],
A = 1,
B = 2,
C = 3,
D = 4,
E = 5,
F = 6,
T = [1, 2, 3] ;
L = [1, 2, 3, 4, 6, 5],
A = 1,
B = 2,
C = 3,
D = 4,
E = 6,
F = 5,
T = [1, 2, 3] ;
.
.
.
Or maybe you don't even want to restrict the sum:
?- L=[A,B,C,D,E,F], all_distinct(L), sum_oftriple_fromlist(S,T,L), L ins 1..6, label(L).
L = [1, 2, 3, 4, 5, 6],
A = 1,
B = 2,
C = 3,
D = 4,
E = 5,
F = S, S = 6, % sum = 6
T = [1, 2, 3] ;
.
.
.
L = [1, 2, 4, 3, 5, 6],
A = 1,
B = 2,
C = 4,
D = 3,
E = 5,
F = 6,
S = 7, % sum = 7
T = [1, 2, 4] ;
.
.
.
As you can see the CLP(FD) version of the predicate resembles a true relation as opposed to the non-CLP(FD) version. And of course your example queries yield the same answers with both versions.
Your code only considers the first 3 items in the list, and not any other combinations.
The most natural way to structure a solution involving a list is to base your recursion on the structure of the list. So:
If the first element of the list (say, X) is to be included in the 3 values that sum to N, we need to find a way to find 2 values in the rest of the list that sum to N-X.
If it isn't, just try to solve the problem using the rest of the list.
Note that you may need a "helper" version of your predicate that allows you to add other parameters. In this case, knowing how many values you need to add up would be helpful.
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.
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