从一组常量中选取2个随机值

时间:2014-02-15 19:49:09

标签: prolog

在Prolog中,如何从一组52张卡中随机选择2个值?即Player1(X,Y),X将是52和Y中的任何一张卡,它们必须是不同的。 Player2将获得相同的待遇,他的牌必须与已经选择的牌不同。感谢。

3 个答案:

答案 0 :(得分:1)

在SWI-Prolog中我会做一个pick_card / 3

pick_card(Cards, Card, Rest) :-
  length(Cards, N), random_between(1, N, R), nth1(R, Cards, Card, Rest).

并应用2次

pick_two_cards(Cards, C1,C2, Rest) :-
  pick_card(Cards, C1, R1),
  pick_card(R1, C2, Rest).

答案 1 :(得分:1)

基本上,任务是从集合[1..52]中抽取4个不同的元素。

在Python中,例如,有一个标准函数,代码是

random.sample(range(1, 52 + 1), 4)

我看过Python如何实现random.sample(range(1..N + 1), K) - 它基本上只是生成随机数[1..N]的K步骤,并且在每一步都只是继续尝试生成随机数,而当前生成的数字已在前一步。它看起来效率低下,但可能需要归档分布的统一性。

让我们为Prolog创建一个类似的(但简化的)sample谓词。

sample(N, K, Sample) :-
    sample(N, K, [], Sample).

sample(_, 0, _, []).
sample(N, K, Selected, [X | Rest]) :-
    K > 0,
    new_random_index(N, Selected, X),
    NewSelected = [X | Selected],
    NewK is K - 1,
    sample(N, NewK, NewSelected, Rest).

new_random_index(N, Selected, X) :-
    ( 
        % Can be implementation-specific. Works in B-Prolog and ECLiPSe CLP.
        X is (random mod N) + 1, 
        \+ membchk(X, Selected) 
    ; 
        new_random_index(N, Selected, X)
    ).

一些测试运行:

| ?- sample(52, 4, Sample).
sample(52, 4, Sample).
Sample = [40,23,38,44] ?
yes
| ?- sample(52, 4, Sample).
sample(52, 4, Sample).
Sample = [2,28,39,17] ?
yes

如果membchk测试更改为使用集合而不是列表测试成员资格的谓词,则可以大大提高程序的效率。但这是特定于实现的。

答案 2 :(得分:1)

如果你想反复绘制随机卡片,最好一次性整理整个列表,然后只需从前面挑选卡片。一些Prolog(例如ECLiPSe)有一个库谓词,所以你可以调用

lists:shuffle(Cards, [Card1,Card2|Rest]).

如果你想自己写洗牌,这是一个巧妙的伎俩:

shuffle(Xs, Rs) :-
    add_random_keys(Xs, KXs),  % add random key to each list element
    keysort(KXs, KRs),         % sort by keys, perturbing original order
    strip_keys(KRs, Rs).       % remove the keys again

add_random_keys([], []).
add_random_keys([X|Xs], [K-X|KXs]) :-
    random(K),
    add_random_keys(Xs, KXs).

strip_keys([], []).
strip_keys([_K-X|KXs], [X|Xs]) :-
    strip_keys(KXs, Xs).
相关问题