私は一般的なポーカーハンドを分析するための述語を書こうとしています。たとえば、「カード」のリストが与えられた場合、プレーヤーが4種類あるかどうかを識別します。3種類の; ペアなど:私の考えは、同様のランクをチェックし、そうでない場合は削除することでした:
これはfourofakind(["A"、 "J"、10、 "Q"、 "A"、 "A"、 "A"])で機能します
ただし、すべてのシナリオではありません。ここでのロジックに関するガイダンスはありますか?
ありがとう
問題は、手札の最初のカードがセットに4回現れるかどうかだけをチェックすることです。すべてのカードに対してそれを行う必要があります。
見たカードの数を数える補助述語を紹介し、4つのセットが見つかるまで、主述語を手札のカードに対して繰り返します。
four([H|T]) :- four0(H,1,T), !. % find a set of four Hs
four([_|T]) :- four(T). % else continue with remaining set
four0(_,4,_) :- !. % found four cards: stop
four0(X,I,[X|T]) :- !,I1 is I+1,four0(X,I1,T). % found another card: inc counter
four0(X,I,[_|T]) :- four0(X,I,T). % else continue
短いリストがなかった場合は、たとえば、すでにチェックしたカードを覚えたり、それらを削除したりすることで、リストを改善できます。また、最初にリストを並べ替えると、はるかに簡単になります。
[H,H,H,H]
ところで、元の最初の句のネストされたリストを。として、2番目の句のネストされたリストを。として簡略化できます[H1,H2|T]
。目にやさしい!
ビルトインをうまく活用することを検討してください。リストを並べ替えると、すべての要素がグループ化され、シーケンスのチェックが簡単になります。
fourofakind(Hand) :- % not intersted to what card is
fourofakind(Hand, _).
fourofakind(Hand, C) :-
msort(Hand, Sorted),
append([_, [C,C,C,C], _], Sorted).
述語には2つの形式があり、後者はカードコードも提供します。msort呼び出しを使用してください:sortを使用すると、重複が失われます...
chacが指摘し、この投稿で再び議論したように、appendを使用すると、非常に簡単にソートされたリストを正常に解析できます。ソートせずに、次のように書くことができます。
fourofakind(Hand, X) :- append([_, [X], _, [X], _, [X], _, [X], _], Hand).
これは基本的にプロローグに伝えます:私は私の手にサブリスト[X]の4倍の間に何かを持たせたいです。
または、@ falseが他のスレッド(DCG)での返信で非常にグラフィカルに魅力的なソリューションとして説明しているものを使用するには、次のようにします。
four --> ..., [X], ..., [X], ..., [X], ..., [X], ... .
... --> [] | [_], ... .
?- Xs = "bacada", phrase(four, Xs).
基本的な再帰を使用して作業を行うことで、あまりにも多くのビルトインを使用することを避けることができます。
three_of_a_kind(Item, [Item|Tail]) :- pair(Item, Tail).
three_of_a_kind(Item, [_Item|Tail]) :- three_of_a_kind(Item, Tail).
pair(Item, [Item|Tail]) :- one(Item, Tail).
pair(Item, [_NotItem|Tail]) :- pair(Item, Tail).
one(Item, [Item|_Tail]).
one(Item, [_NotItem|Tail]) :- one(Item, Tail).
ここでone/2
は、の素朴な定義に相当することに注意してくださいmember/2
。私はあなたにどのようにそして働くかをfour_of_a_kind/1
見ることによってあなたに追加の仕事をさせます!カットの使用は、未使用の選択ポイントを削除するためにも興味深いでしょう。three_of_a_kind/1
pair/2