Created
April 25, 2012 00:12
-
-
Save r3/2484778 to your computer and use it in GitHub Desktop.
Udacity code up to #16
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
def poker(hands): | |
"""Return the best hand: poker([hand,...]) => hand""" | |
# Recall that providing a key is essentially calling | |
# that function on 'hands' and sorting the objects by | |
# the results. | |
return max(hands, key=hand_rank) | |
def card_ranks(cards): | |
"""Return hand sorted by card rank""" | |
# Dictionary, maps between one object and another | |
# ie. conv['T'] => 10 | |
conv = {'T' : 10, 'J' : 11, 'Q' : 12, 'K' : 13, 'A' : 14} | |
# Ternary inside of a list comprehension. Expands to: | |
# | |
# result = [] | |
# for x, y in cards: | |
# if x in conv: | |
# result.append(conv[x]) | |
# else: | |
# result.append(int(x)) | |
# | |
ranks = [conv[x] if x in conv else int(x) for x,y in cards] | |
ranks.sort(reverse = True) | |
return ranks | |
# In the videos, it was done as follows (as opposed to my list | |
# comprehension, but feels like an ugly hack to me. | |
# | |
# ranks = ['--23456789TJQKA'.index(r) for r,s in hand] | |
# ranks.sort(reverse = True) | |
# return ranks | |
def straight(ranks): | |
"""Return True if the ordered ranks form a 5-card straight""" | |
# See below for set information. Notice that we're using | |
# the set to ensure that there are no duplicate card ranks. | |
return (max(ranks) - min(ranks) == 4 and len(set(ranks)) == 5) | |
def flush(hand): | |
"""Return True if all the cards have the same suit.""" | |
suits = [y for x,y in hand] | |
# Remember that a set will remove duplicates: set([1, 2, 3, 1, 3, 4]) | |
# => 1, 2, 3, 4 | |
# Also recognize that sets, like dictionaries, are unordered; | |
# If you choose to iterate over them, do not expect that the | |
# order will remain unchanged. Here, we don't care about the | |
# ordering. We gather a list of all the cards' suits, and ask | |
# if they're all the same by removing duplicates with the 'set' | |
# data model and check that its length is one. | |
return len(set(suits)) == 1 | |
def two_pair(ranks): | |
"""If there are two pair, return the ranks as a tuple | |
(highest, lowest); otherwise return none | |
""" | |
# Create a shallow copy to avoid changing original | |
# (Side effects, especially unexpected ones, are bad) | |
pool = list(ranks) | |
result = [] | |
for count in range(2): | |
found = kind(2, pool) | |
if found: | |
result.append(found) | |
# We remove the found card so that the next call | |
# to 'kind' will not return the same exact pair. | |
pool.remove(found) | |
if len(result) == 2: | |
return tuple(sorted(result, reverse=True)) | |
def kind(number, ranks): | |
"""Returns the rank that occurs 'number' times""" | |
for card in ranks: | |
if ranks.count(card) == number: | |
return card | |
def hand_rank(hand): | |
"""Return a value indicating the ranking of a hand.""" | |
ranks = card_ranks(hand) | |
# Straight Flush -> (8, high_rank) | |
if straight(ranks) and flush(hand): | |
return (8, max(ranks)) | |
# 4 of a kind -> (7, rank, extra) | |
elif kind(4, ranks): | |
return (7, kind(4, ranks), kind(1, ranks)) | |
# Full house -> (6, rank3, rank2) | |
elif kind(3, ranks) and kind(2, ranks): | |
return (6, kind(3, ranks), kind(2, ranks)) | |
# Flush -> (5, [full_sorted_hand]) | |
elif flush(hand): | |
return (5, ranks) | |
# Straight -> (4, high_rank) | |
elif straight(ranks): | |
return (4, max(ranks)) | |
# 3 of a kind -> (3, rank, [full_sorted_hand]) | |
elif kind(3, ranks): | |
return (3, kind(3, ranks), ranks) | |
# 2 pairs -> (2, high_rank, low_rank, [full_sorted_hand]) | |
elif two_pair(ranks): | |
high, low = two_pair(ranks) | |
return (2, high, low, ranks) | |
# 2 of a kind -> (1, rank, [full_sorted_hand]) | |
elif kind(2, ranks): | |
return (1, kind(2, ranks), ranks) | |
# Nothing -> (0, [full_sorted_hand]) | |
else: | |
return (0, ranks) | |
def test(): | |
"""Test cases for the functions in poker program.""" | |
sf = "6C 7C 8C 9C TC".split() # Straight Flush | |
fk = "9D 9H 9S 9C 7D".split() # Four of a Kind | |
fh = "TD TC TH 7C 7D".split() # Full House | |
tp = "5S 5D 9H 9C 6S".split() # Two Pair | |
assert card_ranks(sf) == [10, 9, 8, 7, 6] | |
assert card_ranks(fk) == [9, 9, 9, 9, 7] | |
assert card_ranks(fh) == [10, 10, 10, 7, 7] | |
fkranks = card_ranks(fk) | |
tpranks = card_ranks(tp) | |
assert kind(4, fkranks) == 9 | |
assert kind(3, fkranks) == None | |
assert kind(2, fkranks) == None | |
assert kind(1, fkranks) == 7 | |
assert two_pair(fkranks) == None | |
assert two_pair(tpranks) == (9, 5) | |
assert poker([sf, fk, fh]) == sf | |
assert poker([fk, fh]) == fk | |
assert poker([fh, fh]) == fh | |
assert poker([sf]) == sf | |
assert poker([sf] + 99*[fh]) == sf | |
assert hand_rank(sf) == (8, 10) | |
assert hand_rank(fk) == (7, 9, 7) | |
assert hand_rank(fh) == (6, 10, 7) | |
return 'tests pass' | |
if __name__ == '__main__': | |
print(test()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment