【问题标题】:Prolog: random permutationProlog:随机排列
【发布时间】:2021-01-03 10:06:57
【问题描述】:

我正在尝试使用 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 中获得随机排列?

【问题讨论】:

    标签: random prolog permutation swi-prolog


    【解决方案1】:

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

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

    【讨论】:

    【解决方案2】:

    你可以试试:

    ?- random_permutation([1,2,3,4], P).
    P = [2, 1, 4, 3].
    

    【讨论】:

    • 谢谢你的回答,我不知道已经有一个内置谓词:)
    • 这是swi序言。
    • @peter.cyc 是的!该问题用 SWI-Prolog 标记。
    【解决方案3】:

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

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

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

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

    4. 使用 nth1 为我们提供给定索引的排列。

    5. ! (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]
    

    【讨论】:

    • 感谢您的努力。不幸的是,对于较大的列表,这会变得非常缓慢。
    猜你喜欢
    • 2012-06-24
    • 2012-01-31
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-26
    相关资源
    最近更新 更多