Fall 2014, David Matuszek

- To give you more practice with Clojure syntax

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.

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`

returns the suit of the card, one of*card*)`"C"`

,`"D"`

,`"H"`

,`"S"`

.`(rank`

returns the rank of the card, as an integer in the range 2 to 14. (Hint: Use the Java methods*card*)`(Character/isDigit`

and*char*)`(Integer/valueOf`

. Use a map to convert the characters*string*)`T`

,`J`

,`Q`

,`K`

,`A`

into the numbers 10 through 14.`(pair?`

returns*hand*)`true`

if the hand contains two (but not more than two) cards of the same rank.`(three-of-a-kind?`

returns*hand*)`true`

if the hand contains three (but not four) cards of the same rank.`(four-of-a-kind?`

returns*hand*)`true`

if the hand contains four cards of the same rank.`(flush?`

returns*hand*)`true`

if all the cards have the same suit, but they are not in sequence.`(full-house?`

returns*hand*)`true`

if the hand contains three matching cards of one rank and two matching cards of another rank.`(two-pairs?`

returns*hand*)`true`

if the hand contains two pairs of two different ranks.`(straight?`

returns*hand*)`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?`

returns true if the hand is both a straight and a flush.*hand*)`(value`

returns:*hand*)`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`

returns an ordered list of ranks (integers) of the cards, arranged as follows:*hand*)- Straight, flush, and straight-flush: The ranks in descending order.
- Example:
`(kickers ["2H" "3S" "6C" "5D" "4D"])`

returns`'(6 5 4 3 2)`

.

- Example:
- 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)`

.

- Example:
- 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.

`frequencies`

function. All of the above can be summarized as: Higher frequencies first, equal frequencies in descending order.- Straight, flush, and straight-flush: The ranks in descending order.
`(higher-kicker?`

compares the corresponding values in the two kickers, and returns*kicker1 kicker2*)`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?`

returns*hand1 hand2*)`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 &`

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*hands*)`nil`

if no hands are given.

Useful built-in functions:

`(frequencies`

gives a map from elements in the sequence to the time each element occurs in the sequence.*sequence*)`(keys`

returns the keys in a map.*a-map*)`(vals`

returns the values in a map.*a-map*)`(max &`

returns the largest argument (the*nums*)`&`

indicates zero or more arguments).`(min &`

returns the smallest argument.*nums*)`(apply`

calls the function with the given arguments.*fun list-of-args*)`(sort`

returns a copy of the sequence with the elements in ascending order.*a-seq*)`(range`

returns a sequence of integers starting with the lower bound and going up to, but not including, the upper bound.*lower-bound upper-bound*)`(replace`

replace each element of the sequence that occurs as a key in the map with the corresponding value.*a-map a-sequence*)

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"])
```

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