This question came up while answering another question on StackOverflow on (generalizing a bit) generating all sequences formed out of a finite set of elements with no duplicate occurrences.
As Boris rightly indicated in the comments, there are many existing solutions to this problem. However, I am interested in a solution that does not use an accumulator (i.e., a list of already picked elements against which a newly selected element is to be compared) but that uses dif/2
statements instead.
To illustrate, in my following program I have 4 elements and, after 4 recursive calls, a couple of div/2
statements which state that the 4 elements that have been chosen until now are pairswise dissimilar. From this one can deduce that it makes no sense to continue the recursion and look for a fifth element, since there are no elements left given the div/2
statements. Is there a way to encode this 'knowledge' into the program so that it no longer loops?
:- use_module(library(apply)).
:- use_module(library(dif)).
sequences([]).
sequences([H|T]):-
maplist(dif(H), T),
between(1, 4, H),
sequences(T).
Current, looping behavior:
?- sequences(X).
X = [] ;
X = [1] ;
...
X = [4, 3, 1, 2] ;
X = [4, 3, 2, 1] ;
<LOOP>