Search code examples
randomprologpermutationswi-prolog

Prolog: random permutation


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?


Solution

  • 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.