CIS 554 Clojure Poker
Fall 2014, David Matuszek

# Purposes of this assignment

• To give you more practice with Clojure syntax

# General idea of the assignment

Write and test code to evaluate a Poker hand.

You don't need to know Poker; you can think of this as an abstract exercise. While I believe this assignment is self-contained, you can visit the Wikipedia article on Poker hands for more information.

# Details

Poker cards have a rank (2, 3, 4, 5, 6, 7, 8, 9, 10, Jack=11, Queen=12, King=13, Ace=14) and a suit (Clubs, Diamonds, Hearts, Spades). A card will be represented by a two character string, the first indicating its rank (use `T` for 10), and the second indicating its suit. For example, `"2C"` would be the 2 of Clubs, and `"JH"` would be the Jack of Hearts. A deck of cards consists of 52 (4*13) cards, all different.

A hand consists of a vector of exactly five cards.

Write and test the following methods:

• `(suit card)` returns the suit of the card, one of `"C"`, `"D"`, `"H"`, `"S"`.
• `(rank card)` returns the rank of the card, as an integer in the range 2 to 14. (Hint: Use the Java methods `(Character/isDigit char)` and `(Integer/valueOf string)`. Use a map to convert the characters `T`, `J`, `Q`, `K`, `A` into the numbers 10 through 14.
• `(pair? hand)` returns `true` if the hand contains two (but not more than two) cards of the same rank.
• `(three-of-a-kind? hand)` returns `true` if the hand contains three (but not four) cards of the same rank.
• `(four-of-a-kind? hand)` returns `true` if the hand contains four cards of the same rank.
• `(flush? hand)` returns `true` if all the cards have the same suit, but they are not in sequence.
• `(full-house? hand)` returns `true` if the hand contains three matching cards of one rank and two matching cards of another rank.
• `(two-pairs? hand)` returns `true` if the hand contains two pairs of two different ranks.
• `(straight? hand)` returns `true` if the hand contains five ranks in sequence (for example, `["2H" "3S" "6C" "5D" "4D"]`). An Ace may be counted as rank 1 or rank 14.
• `(straight-flush? hand)` returns true if the hand is both a straight and a flush.
• `(value hand)` returns:  `0` for none of the above `3` for three of a kind `6` for a full house `1` for a pair `4` for a straight `7` for four of a kind `2` for two pairs `5` for a flush `8` for a straight flush
• `(kickers hand)` returns an ordered list of ranks (integers) of the cards, arranged as follows:
• Straight, flush, and straight-flush: The ranks in descending order.
• Example: `(kickers ["2H" "3S" "6C" "5D" "4D"])` returns `'(6 5 4 3 2)`.
• Two pairs: The rank of the higher-ranking pair, the lower-ranking pair, and the rank of the unpaired card.
• Example: `(kickers ["5H" "AD" "5C" "7D" "AS"])` returns `'(14 5 7)`.
• Full house: The rank of the three of a kind, followed by the rank of the two of a kind.
• Four of a kind: The rank of the four of a kind, followed by the rank of the remaining kind.
• Three of a kind: The rank of the three of a kind, the rank of the higher remaining card, the rank of the lower remaining card.
• Pair: The rank of the pair, followed by the ranks of the remaining cards, in descending order.
• None of the above: The ranks in descending order.
Hint: Use the `frequencies` function. All of the above can be summarized as: Higher frequencies first, equal frequencies in descending order.
• `(higher-kicker? kicker1 kicker2)` compares the corresponding values in the two kickers, and returns `true` if the first kicker has the larger value of the first difference, `false` if the second kicker does, or if the lists are pairwise equal. Example: `(higher-kicker? '(8 5 9) '(8 7 3))` should return `false`, because 8==8 but 7>5. Assume that the two kicker lists are of equal lengths.
• `(beats? hand1 hand2)` returns `true` if the value of the first hand is larger than the value of the second hand, or if the values are equal and the first hand has a higher kicker value than the second hand. Returns `nil` in all other cases.
• `(winning-hand & hands)` returns the winning hand (the one that beats all the others) or, in the case of a tie, a sequence (list or vector) of the tied hands. Returns `nil` if no hands are given.

Useful built-in functions:

• `(frequencies sequence)` gives a map from elements in the sequence to the time each element occurs in the sequence.
• `(keys a-map)` returns the keys in a map.
• `(vals a-map)` returns the values in a map.
• `(max & nums)` returns the largest argument (the `&` indicates zero or more arguments).
• `(min & nums)` returns the smallest argument.
• `(apply fun list-of-args)` calls the function with the given arguments.
• `(sort a-seq)` returns a copy of the sequence with the elements in ascending order.
• `(range lower-bound upper-bound)` returns a sequence of integers starting with the lower bound and going up to, but not including, the upper bound.
• `(replace a-map a-sequence)` replace each element of the sequence that occurs as a key in the map with the corresponding value.

# Unit tests

Here are some sample hands you can use for testing.

``````(def high-seven                   ["2H" "3S" "4C" "5C" "7D"])
(def pair-hand                    ["2H" "2S" "4C" "5C" "7D"])
(def two-pairs-hand               ["2H" "2S" "4C" "4D" "7D"])
(def three-of-a-kind-hand         ["2H" "2S" "2C" "4D" "7D"])
(def four-of-a-kind-hand          ["2H" "2S" "2C" "2D" "7D"])
(def straight-hand                ["2H" "3S" "6C" "5D" "4D"])
(def low-ace-straight-hand        ["2H" "3S" "4C" "5D" "AD"])
(def high-ace-straight-hand       ["TH" "AS" "QC" "KD" "JD"])
(def flush-hand                   ["2H" "4H" "5H" "9H" "7H"])
(def full-house-hand              ["2H" "5D" "2D" "2C" "5S"])
(def straight-flush-hand          ["2H" "3H" "6H" "5H" "4H"])
(def low-ace-straight-flush-hand  ["2D" "3D" "4D" "5D" "AD"])
(def high-ace-straight-flush-hand ["TS" "AS" "QS" "KS" "JS"])``````

# Notes

Some of this assignment is "borrowed" from a very good online Clojure course. (Solutions are not provided! )

# Due date

Turn your assignment in to Canvas before 6am Friday, October 10. (This is to give you a chance to enjoy Fall break. However, expect a new assignment on Wednesday, October 8.)