; ranks are 2-14 with 2 being two, 13 being king, and 14 being ace ; suits are 1-4 with no particular labelling ; takes a list of cards (rank . suit) and returns the value of the best poker ; hand which can be made with them ; returned list is hand type followed by cards in descending order ; doesn't work for ten or more cards if there are multiple flushes ; all sorting is done highest to lowest ( (defconstant STRAIGHT_FLUSH 9) (defconstant FOUR_OF_A_KIND 8) (defconstant FULL_HOUSE 7) (defconstant FLUSH 6) (defconstant STRAIGHT 5) (defconstant THREE_OF_A_KIND 4) (defconstant TWO_PAIR 3) (defconstant PAIR 2) (defconstant HIGH_CARD 1) (defun find_flush_inner (suits last count) (if (not suits) 0 (if (= (f suits) last) (if (= count 4) last (find_flush_inner (r suits) last (+ count 1)) ) (find_flush_inner (r suits) (f suits) 1) ) ) ) ; returns the flush suit or 0 if there isn't any ; suits must be clustered/sorted (defun find_flush (suits) (find_flush_inner (sort (lambda (x y) (deep> x y)) suits) 0 0) ) (defun straight_high_inner (ranks started_ace last count) (if (not ranks) ; at the end of the list (if (logand (= last 2) (= count 4) started_ace) ; ace to five 5 ; no straight 0 ) (if (= last (f ranks)) ; skip identical cards (straight_high_inner (r ranks) started_ace last count) ; if the partial straight continues (if (= (f ranks) (- last 1)) (if (= count 4) ; found a straight, add 3 to last because next and last are included (+ last 3) ; keep looking for a straight with the count going up by one (straight_high_inner (r ranks) started_ace (f ranks) (+ count 1)) ) ; reset the count (straight_high_inner (r ranks) started_ace (f ranks) 1) ) ) ) ) ; returns the high card of a straight or 0 if there isn't any ; ranks must be sorted in descending order (defun straight_high (ranks) (straight_high_inner ranks (= (f ranks) 14) 0 0) ) (defun group_by_count_inner (items last count) (if (not items) (list (c count last)) (if (= (f items) last) (group_by_count_inner (r items) last (+ count 1)) (assign val (group_by_count_inner (r items) (f items) 1) (c (c count last) val) ) ) ) ) (defun group_by_count (items) (group_by_count_inner items (f items) 0) ) (defun handcalc (cards) (assign-lambda first (lambda (x) (f x)) rest (lambda (x) (r x)) fsuit (find_flush (map rest cards)) max_flush (if (not fsuit) 0 (assign-lambda fnosuits (sort (lambda (x y) (deep> x y)) (filtermap (lambda ((& fsuit) (card_rank . card_suit)) (if (= fsuit card_suit) card_rank 0 ) ) cards 0 ) ) fsh (straight_high fnosuits) (if fsh (list STRAIGHT_FLUSH fsh) (c FLUSH (slice fnosuits 5)) ) ) ) nosuits (sort (lambda (x y) (deep> x y)) (map first cards)) sh (straight_high nosuits) max_straight (if sh (list STRAIGHT sh) 0 ) groups (sort (lambda (x y) (deep> x y)) (group_by_count nosuits)) (top_count . top_card) (f groups) (second_count . second_card) (f (r groups)) topcards (map rest groups) max_group (if (= top_count 1) (c HIGH_CARD (slice topcards 5)) (if (= top_count 2) (if (= second_count 1) (c PAIR (slice topcards 4)) (c TWO_PAIR (slice topcards 3)) ) (if (= top_count 3) (if (= second_count 1) (c THREE_OF_A_KIND (slice topcards 3)) (c FULL_HOUSE (slice topcards 2)) ) (c FOUR_OF_A_KIND (slice topcards 2)) ) ) ) (max (lambda (x y) (deep< x y)) (list max_flush max_straight max_group)) ) ) )