Prolog:随机排列
Prolog: random permutation
我正在尝试使用 prolog 进行随机排列。但问题是
?- permutation([1,2,3,4],L).
总是给出 L = [1, 2, 3, 4]
作为第一个答案。我可以使用查询
来解决这个问题
?- L1=[1,2,3,4], permutation(L1,L2), dif(L1,L2).
但这总是给我 L2 = [1, 2, 4, 3]
作为第一个答案。
如何在 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,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).
等等:
?- 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.
如果我们还保留有关按顺序选择哪些元素的信息,我们可以编写一个“反转排列”的谓词,因为在创建它时没有信息丢失。
你可以试试:
?- random_permutation([1,2,3,4], P).
P = [2, 1, 4, 3].
我只是给出一个替代方法。
使用 findall 获取所有可能的排列。
获取包含排列的列表的长度。
使用random生成0到长度之间的随机数。这将用作索引值。
使用 nth1 给我们一个给定索引的排列。
! (Cut) 用于只给出一个值。如果您想要更多值,请将其删除。
例子:-
perm([H|T],Permutation):-
findall(A,permutation([H|T],A),List),
length(List,Length),
random(1,Length,Random),
nth1(Random,List,Permutation),!.
?- perm([1,2,3,4],Permutation).
Permutation = [1, 4, 3, 2]
?- perm([1,2,3,4],Permutation).
Permutation = [3, 1, 2, 4]
?- perm([1,2,3,4],Permutation).
Permutation = [3, 1, 4, 2]
我正在尝试使用 prolog 进行随机排列。但问题是
?- permutation([1,2,3,4],L).
总是给出 L = [1, 2, 3, 4]
作为第一个答案。我可以使用查询
?- L1=[1,2,3,4], permutation(L1,L2), dif(L1,L2).
但这总是给我 L2 = [1, 2, 4, 3]
作为第一个答案。
如何在 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,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).
等等:
?- 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.
如果我们还保留有关按顺序选择哪些元素的信息,我们可以编写一个“反转排列”的谓词,因为在创建它时没有信息丢失。
你可以试试:
?- random_permutation([1,2,3,4], P).
P = [2, 1, 4, 3].
我只是给出一个替代方法。
使用 findall 获取所有可能的排列。
获取包含排列的列表的长度。
使用random生成0到长度之间的随机数。这将用作索引值。
使用 nth1 给我们一个给定索引的排列。
! (Cut) 用于只给出一个值。如果您想要更多值,请将其删除。
例子:-
perm([H|T],Permutation):-
findall(A,permutation([H|T],A),List),
length(List,Length),
random(1,Length,Random),
nth1(Random,List,Permutation),!.
?- perm([1,2,3,4],Permutation).
Permutation = [1, 4, 3, 2]
?- perm([1,2,3,4],Permutation).
Permutation = [3, 1, 2, 4]
?- perm([1,2,3,4],Permutation).
Permutation = [3, 1, 4, 2]