Last active
December 29, 2015 11:59
-
-
Save benstopford/7667590 to your computer and use it in GitHub Desktop.
Scoring a poker hand in Clojure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(require '[clojure.test :refer :all ]) | |
;flush | |
(defn flush? | |
[hand] | |
(= 1 (count | |
(distinct | |
(map first hand))))) | |
;straight | |
(defn straight? | |
[hand] | |
(let [[min-value :as sorted] (sort (map second hand))] | |
(= sorted | |
(take 5 | |
(iterate inc min-value))))) | |
;n of a kind | |
(defn most-popular-numbers | |
[hand] (sort > | |
(map second | |
(frequencies | |
(map second hand))))) | |
(defn n-of-kind? | |
[n hand] | |
(= n | |
(first | |
(most-popular-numbers hand)))) | |
;two pair | |
(defn two-pair? | |
[hand] | |
(= '(2 2) | |
(take 2 | |
(most-popular-numbers hand)))) | |
;full house | |
(defn full-house? | |
[hand] | |
(= '(3 2) | |
(take 2 | |
(most-popular-numbers hand)))) | |
;straight flush | |
(defn straight-flush? | |
[hand] | |
(and (straight? hand) | |
(flush? hand))) | |
;high card | |
(defn high-card? | |
[hand] | |
(first | |
(sort > | |
(map second hand)))) | |
;royal flush | |
(defn royal-flush? | |
[hand] | |
(and | |
(straight-flush? hand) | |
(= 14 (high-card? hand)))) | |
(defn score | |
[hand] | |
(cond | |
(royal-flush? hand) 200 | |
(straight-flush? hand) 190 | |
(n-of-kind? 4 hand) 180 | |
(full-house? hand) 170 | |
(flush? hand) 160 | |
(straight? hand) 150 | |
(n-of-kind? 3 hand) 140 | |
(two-pair? hand) 130 | |
(n-of-kind? 2 hand) 120 | |
:else (high-card? hand) | |
) | |
) | |
(defn deck [] | |
(for | |
[suit '(:clubs :hearts :diamonds :spades ) | |
number (range 2 15)] | |
[suit number])) | |
;takes a pack of cards and deals, ensuring no repetition | |
(defn deal | |
[pack hands hand-count] | |
(if (> (count pack) 5) | |
(deal | |
(drop 5 pack) | |
(cons | |
(take 5 pack) | |
hands) | |
hand-count) | |
(take hand-count hands))) | |
(defn deal-n-hands [n] | |
(deal | |
(shuffle (deck)) | |
'() n)) | |
(defn score-and-print [hand] | |
(format "Score of %s for hand %s" (score hand) (apply str hand))) | |
;Run me | |
(pprint (map score-and-print (deal-n-hands 8))) | |
;----- | |
; tests | |
(def hand-flush [[:diamonds 3] [:diamonds 5] [:diamonds 9] [:diamonds 6] [:diamonds 4]]) | |
(def hand-straight [[:diamonds 3] [:diamonds 4] [:diamonds 5] [:spades 6] [:clubs 7]]) | |
(def hand-four-of-kind [[:clubs 3] [:diamonds 3] [:spades 3] [:hearts 3] [:clubs 7]]) | |
(def hand-three-of-kind [[:clubs 3] [:diamonds 3] [:spades 3] [:hearts 5] [:clubs 7]]) | |
(def hand-pair [[:clubs 3] [:diamonds 3] [:spades 4] [:hearts 9] [:clubs 7]]) | |
(def hand-two-pair [[:clubs 3] [:diamonds 3] [:spades 4] [:hearts 4] [:clubs 7]]) | |
(def hand-full-house [[:clubs 3] [:diamonds 3] [:spades 4] [:hearts 4] [:clubs 4]]) | |
(def hand-straight-flush [[:diamonds 3] [:diamonds 4] [:diamonds 5] [:diamonds 6] [:diamonds 7]]) | |
(def hand-royal-flush [[:diamonds 10] [:diamonds 11] [:diamonds 12] [:diamonds 13] [:diamonds 14]]) | |
;test specific hands | |
(is (= true (flush? hand-flush))) | |
(is (= false (flush? hand-straight))) | |
(is (= true (straight? hand-straight))) | |
(is (= false (straight? hand-flush))) | |
(is (= true (n-of-kind? 4 hand-four-of-kind))) | |
(is (= false (n-of-kind? 4 hand-three-of-kind))) | |
(is (= true (n-of-kind? 3 hand-three-of-kind))) | |
(is (= false (n-of-kind? 3 hand-four-of-kind))) | |
(is (= true (n-of-kind? 2 hand-pair))) | |
(is (= false (n-of-kind? 2 hand-flush))) | |
(is (= true (two-pair? hand-two-pair))) | |
(is (= false (two-pair? hand-straight-flush))) | |
(is (= true (full-house? hand-full-house))) | |
(is (= false (full-house? hand-flush))) | |
(is (= true (straight-flush? hand-straight-flush))) | |
(is (= false (straight-flush? hand-two-pair))) | |
(is (= 7 (high-card? hand-straight))) | |
(is (= 4 (high-card? hand-full-house))) | |
(is (= true (royal-flush? hand-royal-flush))) | |
(is (= false (royal-flush? hand-four-of-kind))) | |
;test scoring | |
(is (= 200 (score hand-royal-flush))) | |
(is (= 130 (score hand-two-pair))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment