Reputation: 117
Let's say I have a list L1 = [1,2,3], I want to write a predicate that can find all permutations of this list i.e
[1,2,3]
[1,3,2]
[2,1,3]
[2,3,1]
[3,1,2]
[3,2,1]
Note: I know permutation(L1, L2).
does exactly this, but I want to write my own predicate that does this for an exercise.
I'm a prolog rookie, so I thought lets first make a predicate that returns true
when two lists L1 and L2 are permutations of eachother. The requirements for that are:
So I came up with this:
permute(L1,L2):-
forall(member(X,L1), member(X,L2)), % every element that is a member in L1 has to be a member in L2
length(L1,A), % the length of the list L1 is A
length(L2,A). % AND the length of the list L2 is A
So when I query permute([1,2,3], [1,3,2]).
I do get true
as expected, and permute([1,2,3], [1,3]).
and permute([1,2,3], [1,3,4]).
both give false. So my predicate works to see if 2 lists are permutations of eachother.
But if I ask: permute([1,2,3], A).
I want to be able to see all valid A, i.e all permutations of [1,2,3]. Instead I get unbounded variables.
Something like A = [_942, _948, _954].
Why does this happen, why can't i look through all possible lists A? Is there a simple way to modify my code to make that happen?
Upvotes: 2
Views: 215
Reputation: 71074
First of all your two points definition is wrong. According to it, permute( [1,1,2], [1,2,2])
should hold (and it does).
The "simple" way is to use select/3
,
select( [A|B], X):- select(A, X, Y), select(B, Y).
select( [], []).
And it works, but only in one direction. Even adding (simple) same_length
doesn't help:
permute( A, B):- same_length( A, B), select( B, A).
same_length( A, B):- length(A, N), length(B, N). % wrong
% permute( [1,2,3], X). % OK
% permute( X, [1,2,3]). % doesn't terminate after the last solution
No, same_length/2
must be defined carefully, as
same_length( [], []).
same_length( [_|A], [_|B]):- same_length(A, B).
Then permute
is OK in both directions.
Upvotes: 2