As a simple exercise, I wrote my own permutation.
This stack overflows:
without(_, [], []).
without(A, [A|T], T).
without(A, [H|T], [H|G]) :- without(A, T, G).
my_permutation([], []).
my_permutation([H|T], P) :- member(H, P), without(H, P, Pp), my_permutation(T, Pp).
this works partly, but still stack overflows after giving some of the solution space:
without(_, [], []).
without(A, [A|T], T).
without(A, [H|T], [H|G]) :- without(A, T, G).
my_permutation([], []).
my_permutation([H|T], P) :- my_permutation(T, Pp), member(H, P), without(H, P, Pp).
this also stack overflows:
without(A, [A|T], T).
without(A, [H|T], [H|G]) :- without(A, T, G).
my_permutation([], []).
my_permutation([H|T], P) :- without(H, P, Pp), my_permutation(T, Pp).
but this works perfectly:
without(A, [A|T], T).
without(A, [H|T], [H|G]) :- without(A, T, G).
my_permutation([], []).
my_permutation([H|T], P) :- my_permutation(T, Pp), without(H, P, Pp).
Can anyone please help me understand why?
The problem is this portion:
Both P and Pp are uninstantiated, so
withoutcheerfully goes into an infinite loop of giving them an increasingly longer length, as per the T and G variables.Demonstration:
The solution is to replace:
... so that the list length is restricted, causing termination.
This would suffice (although using
same_lengthmakes it slower):Or, more efficiently (using E as a short name for "Element", i.e. element of a list):
This clearly ties both arguments of
my_permutationto be the same length, and passes an instantiated list ([H|T]) towithout.However, it can still have the problem of passing an uninstantiated list to
without, if its arguments are swapped:The advantage of
my_permutation(T, Pp), without(H, P, Pp)is that both arguments ofmy_permutationwill have encountered[], [], and so have their length known. It is still not perfect, though:Note that permutation/2 does not have this problem.
To fix this termination issue, could enforce
same_lengthin a more efficient way:Although, it's faster with those 2 constraint lines flipped in order.
Other permutation methods are shown at https://stackoverflow.com/a/74655536