I'm trying to get random permutation with prolog. But the problem is
?- permutation([1,2,3,4],L).
gives always L = [1, 2, 3, 4]
as first answer. I could fix this by using the query
?- L1=[1,2,3,4], permutation(L1,L2), dif(L1,L2).
But this gives me always L2 = [1, 2, 4, 3]
as first answer.
How can I get a random permutation in SWI Prolog?
Isn't [1,2,3,4]
random enough? Looks random to me!
But I know what you mean - you want a permutation which looks more random.
Why not roll your own? Just pick the next element out of an ever-shrinking "input list".
This is a bit laborious. Maybe there are more elegant ways?
look_random_dammit([],[]) :- !.
% note that [PickedElement|PermutedList] APPENDS "PickedElement"
% to list being constructed. Appending or prepending does not
% really make a difference here though:
look_random_dammit(ListRemainder,[PickedElement|PermutedList]) :-
ListRemainder \== [],
length(ListRemainder,Length),
succ(Max,Length),
% We are now leaving logicland and asking an oracle to give
% use a random number. "Buckle your seatbelt Dorothy, 'cause
% Kansas is going bye-bye!"
random_between(0,Max,PickedIndex),
nth0(PickedIndex,ListRemainder,PickedElement),
length(Prefix,PickedIndex),
% Constructing a remainder list is probably slow
append([Prefix,[PickedElement],Suffix],ListRemainder) ,
append(Prefix,Suffix,ListRemainderNext),
look_random_dammit(ListRemainderNext,PermutedList).
And so:
?- look_random_dammit([1,2,3,4],P).
P = [2,3,1,4] ;
false.
?- look_random_dammit([],P).
P = [] ;
false.
?- look_random_dammit([1,1,1,2,2],P).
P = [2,1,1,2,1] ;
false.
If we also retained the information about which elements was picked in equence, we could write a predicate that "reverses the permutation" because no information was lost while creating it.