Skip to content

Instantly share code, notes, and snippets.

@benstopford
Last active December 29, 2015 11:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benstopford/7667590 to your computer and use it in GitHub Desktop.
Save benstopford/7667590 to your computer and use it in GitHub Desktop.
Scoring a poker hand in Clojure
(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