序言:随机排列

问题描述

我正在尝试使用 prolog 进行随机排列。但问题是

smart_open

总是给出 ?- permutation([1,2,3,4],L). 作为第一个答案。我可以通过使用查询解决这个问题

L = [1,4]

但这给我总是 ?- L1=[1,permutation(L1,L2),dif(L1,L2). 作为第一答案。

如何在 SWI Prolog 中获得随机排列?

解决方法

[1,2,3,4] 还不够随机吗?对我来说看起来很随意!

但我知道你的意思 - 你想要一个看起来 more random 的排列。

为什么不自己动手?只需从不断缩小的“输入列表”中选择下一个元素即可。

这有点费力。或许还有更优雅的方式?

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,% 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,% Constructing a remainder list is probably slow
   append([Prefix,[PickedElement],Suffix],ListRemainder),append(Prefix,Suffix,ListRemainderNext),look_random_dammit(ListRemainderNext,PermutedList).

所以:

?- look_random_dammit([1,4],P).
P = [2,1,4] ;
false.

?- look_random_dammit([],P).
P = [] ;
false.

?- look_random_dammit([1,2],1] ;
false.

如果我们还保留了按顺序选择了哪些元素的信息,我们可以编写一个谓词“反转排列”,因为在创建它时没有信息丢失。

,

你可以试试:

?- random_permutation([1,4,3].
,

我只是提供一种替代方法。

  1. 使用 findall 获取所有可能的排列。

  2. 获取包含排列的列表的长度。

  3. 使用random生成0到长度之间的随机数。这将用作索引值。

  4. 使用 nth1 给我们一个给定索引的排列。

  5. ! (Cut) 仅用于给出一个值。如果您想要更多值,请删除它。

示例:-

perm([H|T],Permutation):-
findall(A,permutation([H|T],A),List),length(List,random(1,Length,Random),nth1(Random,List,Permutation),!.


?- perm([1,Permutation).
Permutation = [1,2]

?- perm([1,Permutation).
Permutation = [3,4]

?- perm([1,2]