I'm trying a college assignment in Prolog, and I have some questions. This is the exercise text, I hope it's clear I'm translating from Italian:
Write a predicate
arrange(List1, List2, K)that when given aList1of at least two elements with only numbers between the range[0..100], is satisfied whenList2is a list obtained re-shuffling the elements ofList1in a way that the absolute difference between two consecutive elements is always greater thanK.
Example:
?- arrange([1, 2, 3], L2, 0).
L2 = [1, 2, 3];
L2 = [1, 3, 2];
L2 = [2, 1, 3];
L2 = [2, 3, 1];
L2 = [3, 1, 2];
L2 = [3, 2, 1];
I've tried to create my own solution, but it doesn't give me all the possible results, instead, I get only one of the possible result. I also have a colleague's solution that gives all the results, but it has one problem that I was trying to fix.
Here's my solution:
arrange(L1,L3,Diff):-
arrange(L1,[],L3,Diff).
arrange(L1,L2,L3,Diff):-
same_length(L1,L3),
shuffle(L1,L2,L3),
constraint(L3,Diff).
constraint([X1,X2],Diff):-
int_0_100(X1),
int_0_100(X2),
diff(X1,X2,Diff).
constraint([X1,X2|Others],Diff):-
int_0_100(X1),
int_0_100(X2),
diff(X1,X2,Diff),
constraint([X2|Others],Diff).
shuffle([],L2,L2).
shuffle([X1|Others],L2,L3):-
L4 = [X1 | L2],
shuffle(Others,L4,L3).
diff(X1,X2,Diff):-
X1 >= X2,
X1 - X2 > Diff.
diff(X1,X2,Diff):-
X1 < X2,
X2 - X1 > Diff.
int_0_100(N):-
N >= 0, N =< 100.
same_length([],[]).
same_length([_|Others1],[_|Others2]):-
same_length(Others1,Others2).
I guess that the problem is that I instantiate a L4 list that can't change in the shuffle predicate.
Now my colleague's solution:
arrange(L1,L2,Diff):-
same_length(L1,L2),
shuffle(L1,L2),
constraint(L2,Diff).
constraint([X1,X2],Diff):-
int_0_100(X1),
int_0_100(X2),
diff(X1,X2,Diff).
constraint([X1,X2|Others],Diff):-
int_0_100(X1),
int_0_100(X2),
diff(X1,X2,Diff),
constraint([X2|Others],Diff).
shuffle([],_).
shuffle([X1|Others],L2):-
member(X1,L2),
shuffle(Others,L2).
diff(X1,X2,Diff):-
X1 >= X2,
X1 - X2 > Diff.
diff(X1,X2,Diff):-
X1 < X2,
X2 - X1 > Diff.
int_0_100(N):-
N >= 0, N =< 100.
same_length([],[]).
same_length([_|Others1],[_|Others2]):-
same_length(Others1,Others2).
As you can see there is one major difference:
In the shuffle predicate He uses
member(X1,L2), I useL4 = [X1 | L2],shuffle(Other,L4,L3).member(X1,L2)gives an error if we have a list with two (or more) equal elements.For Example:
arrange([1,2,3,4,1], List2, 1). Sincemember(1, L2)is alreadytrue(the second time), and sinceL2has initially the same number of elements ofL1(but not instantiated) withsame_length, it doesn't add another1inL2and when we get toint_0_100we get anelement not enough instantiatederror.
This is the problem I was trying to fix, but it seems that if I don't specifically use member, instead of my solution, it just gives one possible answer.
Can you explain to me why that is, and a possible solution of the problem that the predicate member gives?
Thanks in advance for your time, I hope everything's clear enough: English is not my native language, and the problem itself is quite complicated to explain.