Search code examples
prologdcg

Poker Hand in Prolog


I am trying to write a predicate to analyse common poker hands; for example given a list of "cards" identify if the player has 4 of a kind; 3 of a kind; pair etc: My idea was to check for similar rank and remove if not:

this works for fourofakind(["A","J",10,"Q","A","A","A"])

but not all scenarios; any guidance on the logic here?

Thanks


Solution

  • As chac pointed out and to have again the debate we had in this post, you can use append to successfully parse your list once sorted quite easily. Without sorting, you could write :

    fourofakind(Hand, X) :- append([_, [X], _, [X], _, [X], _, [X], _], Hand).
    

    This basically tells prolog : I want my hand to have 4 times the sublist [X] with anything in-between.

    Or, to use what @false describes as a very graphically appealing solution in his reply on the other thread (DCGs) :

    four --> ..., [X], ..., [X], ..., [X], ..., [X], ... .
    
    ... --> [] | [_], ... .
    
    ?- Xs = "bacada", phrase(four, Xs).
    

    You could too avoid using too many built-ins by doing the work with basic recursion :

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

    Note that here one/2 is equivalent to the naive definition of member/2. I let you the task of adding four_of_a_kind/1 by looking at how three_of_a_kind/1 and pair/2 work ! Use of cut would be interesting too to remove unused choice points.