2014-02-15 64 views
0

在Prolog中,我如何從一組52個卡中隨機挑選2個值?即玩家1(X,Y),X將是52和Y中的任何一張牌,並且它們必須是不同的。玩家2將得到相同的待遇,他的牌必須與已經選擇的牌不同。謝謝。從一組常量中挑選2個隨機值

回答

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). 
+0

哇有趣enouth 。我不清楚的唯一部分是謂詞nth1。如果我沒有錯,它會將Card與發現的隨機數聯繫起來。如果是這樣,那麼爲什麼休息呢? – vincent

+0

只是爲了保持pick_card *可重用*。添加輸入/輸出卡/休息你可以在更廣泛的範圍內重複使用。否則,只需「放棄」不需要的輸出參數 - 即所謂的投影... – CapelliC

1

基本上,任務是採樣來自集合[1 4個不同元件.. 52。

在Python中,例如,對於這個標準的功能,而且代碼會

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

我看着Python中如何實現random.sample(range(1..N + 1), K) - 它是生成隨機數的基本上只是k步[1 ..N],並在每一步只是不斷嘗試生成隨機數,而當前生成的數已經在上一步中選擇。它看起來效率不高,但可能需要對分佈的統一性進行歸檔。

讓我們爲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測試改變爲測試使用隸屬集,而不是列出了謂詞得到極大改善。但是這是非常具體的實現。

+0

謝爾蓋對我來說太複雜了。希望在未來的將來我能理解它。 – vincent

1

如果您想重複繪製隨機卡片,最好一次性將整個列表隨機洗牌,然後從前面挑選卡片。有些Prologs(如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).