sequential style:
In [4]:
def ss(nums):
total=0
for i in range(len(nums)):
total=total+nums[i]**2
return total
functional style (P):
In [9]:
def ss(nums):
return sum(x**2 for x in nums)
set
If you don't know what a set() is, don't worry! The set() function is used for identifying all the unique elements in an iterable object (like a list). For example:
myset = set(['one','two','three','two','one'])
myset set(['three', 'two', 'one'])
There are two interesting things to note here: one, set() doesn't keep duplicate copies and two, set() is unordered
tuple
The second answer choice uses a data structure that you didn't see if you took CS 101. (11, 'S') is an example of a tuple. For now, you can think of a tuple as an immutable (unchangeable) list
In [13]:
print max([3,4,5,0]),max([3,4,-5,0],key=abs)
In [ ]:
##test function pokers()
def test():
"Test cases for the functions in poker program"
sf = "6C 7C 8C 9C TC".split() # => ['6C', '7C', '8C', '9C', 'TC']
fk = "9D 9H 9S 9C 7D".split()
fh = "TD TC TH 7C 7D".split()
assert poker([sf, fk, fh]) == sf
# Add 2 new assert statements here. The first
# should check that when fk plays fh, fk
# is the winner. The second should confirm that
# fh playing against fh returns fh.
assert poker([fk, fh]) == fk
assert poker([fh, fh]) == fh
# Add 2 new assert statements here. The first
# should assert that when poker is called with a
# single hand, it returns that hand. The second
# should check for the case of 100 hands.
assert poker([sf]) == sf
assert poker([sf]+99*[fh]) == sf
return "tests pass"
print test()
functions
In [72]:
import random
import math
import itertools
from collections import defaultdict
def poker(hands):
"Return a list of winning hands: poker([hand,...]) => [hand,...]"
return allmax(hands, key = hand_rank)
def allmax(iterable, key=lambda x:x):
"Return a list of all items equal to the max of the iterable."
maxi = max(iterable, key=key)
return [element for element in iterable if key(element) == key(maxi)]
def hand_rank(hand):
"Return a value indicating how high the hand ranks."
# counts is the count of each rank
# ranks lists corresponding ranks
# E.g. '7 T 7 9 7' => counts = (3, 1, 1); ranks = (7, 10, 9)
groups = group(['--23456789TJQKA'.index(r) for r, s in hand])
counts, ranks = unzip(groups)
if ranks == (14, 5, 4, 3, 2):
ranks = (5, 4, 3, 2, 1)
straight = len(ranks) == 5 and max(ranks)-min(ranks) == 4
flush = len(set([s for r, s in hand])) == 1
return (
9 if (5, ) == counts else
8 if straight and flush else
7 if (4, 1) == counts else
6 if (3, 2) == counts else
5 if flush else
4 if straight else
3 if (3, 1, 1) == counts else
2 if (2, 2, 1) == counts else
1 if (2, 1, 1, 1) == counts else
0), ranks
def group(items):
"Return a list of [(count, x)...], highest count first, the highest x first"
groups = [(items.count(x), x) for x in set(items)]
return sorted(groups, reverse = True)
def unzip(pairs):
return zip(*pairs)
def card_ranks(hand):
"Return a list of the ranks, sorted with higher first."
# ranks = ['--23456789TJQKA'.index(r) for r, s in hand]
# ranks = [{'A':14,
# 'K':13,
# 'Q':12,
# 'J':11,
# 'T':10,
# }.get(r,r) for r, s in hand]
ranks = [14 if r == 'A' else
13 if r == 'K' else
12 if r == 'Q' else
11 if r == 'J' else
10 if r == 'T' else
int(r)
for r, s in hand]
ranks.sort(reverse = True)
return ranks if ranks != [14, 5, 4, 3, 2] else [5, 4, 3, 2, 1]
def straight(ranks):
"Return True if the ordered ranks form a 5-card straight."
return sum(ranks) - min(ranks)*5 == 10
def flush(hand):
"Return True if all the cards have the same suit."
suits = [s for r, s in hand]
return len(set(suits)) == 1
def two_pair(ranks):
"""If there are two pair, return the two ranks as a
tuple: (highest, lowest); otherwise return None."""
result = [r for r in set(ranks) if ranks.count(r) == 2]
if len(result) == 2:
return (max(result), min(result))
def kind(n, ranks):
"""Return the first rank that this hand has exactly n of.
Return None if there is no n-of-a-kind in the hand."""
for r in set(ranks):
if ranks.count(r) == n:
return r
return None
deck = [r+s for r in '23456789TJQKA' for s in 'SHDC']
def deal(numhands, n = 5, deck = [r+s for r in '23456789TJQKA' for s in 'SHDC']):
"Return a list of numhands hands consisting of n cards each"
random.shuffle(deck)
deck = iter(deck)
return [[next(deck) for card in range(n)] for hand in range(numhands)]
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
s1 = "AS 2S 3S 4S 5C".split() # A-5 straight
s2 = "2C 3C 4C 5S 6S".split() # 2-6 straight
s3 = "TC JC QC KS AS".split() # 10-A straight
tp = "5S 5D 9H 9C 6S".split() # two pair
ah = "AS 2S 3S 4S 6C".split() # A high
sh = "2S 3S 4S 6C 7D".split() # 7 high
assert poker([sf, fk, fh]) == [sf]
assert poker([fk, fh]) == [fk]
assert poker([fh, fh]) == [fh, fh]
assert poker([sf]) == [sf]
assert poker([sf] + 99*[fh]) == [sf]
assert poker([s1, s2]) == [s2]
assert poker([s1, tp]) == [s1]
# assert hand_rank(sf) == (8, 10)
# assert hand_rank(fk) == (7, 9, 7)
# assert hand_rank(fh) == (6, 10, 7)
# assert hand_rank(s1) == (4, 5)
# assert hand_rank(s3) == (4, 14)
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]
assert card_ranks(['AC', '3D', '4S', 'KH']) == [14, 13, 4, 3]
# Ace-high beats 7-high
assert (card_ranks(['AS', '2C', '3D', '4H', '6S']) >
card_ranks(['2D', '3S', '4C', '6H', '7D']))
# 5-straight loses to 6-straight
assert (card_ranks(['AS', '2C', '3D', '4H', '5S']) <
card_ranks(['2D', '3S', '4C', '5H', '6D']))
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(tpranks) == (9, 5)
assert two_pair([10, 10, 5, 5, 2]) == (10, 5)
assert straight([9, 8, 7, 6, 5]) == True
assert straight([9, 8, 8, 6, 5]) == False
assert flush(sf) == True
assert flush(fk) == False
return 'tests pass'
hand_names = [
'High Card',
'Pair',
'2 Pair',
'3 Kind',
'Straight',
'Flush',
'Full House',
'4 Kind',
'Straight Flush',
]
def hand_percentages(n = 700*1000):
"Sample n random hands and print a table of percentages for each type of hand"
counts = [0]*9
for i in range(n/10):
for hand in deal(10):
ranking = hand_rank(hand)[0]
counts[ranking] += 1
for i in reversed(range(9)):
print('%14s: %6.3f'%(hand_names[i], 100.*counts[i]/n))
def all_hand_percentages():
"Print an exhaustive table of frequencies for each type of hand"
counts = [0]*9
n = 0
deck = [r+s for r in '23456789TJQKA' for s in 'SHDC']
for hand in itertools.combinations(deck, 5):
n += 1
ranking = hand_rank(hand)[0]
counts[ranking] += 1
for i in reversed(range(9)):
print('%14s: %7d %6.3f'%(hand_names[i], counts[i], 100.*counts[i]/n))
def shuffle1(deck):
# O(N**2)
# incorrect distribution
N = len(deck)
swapped = [False] * N
while not all(swapped):
i, j = random.randrange(N), random.randrange(N)
swapped[i] = swapped[j] = True
deck[i], deck[j] = deck[j], deck[i]
def shuffle2(deck):
# O(N**2)
# incorrect distribution?
N = len(deck)
swapped = [False] * N
while not all(swapped):
i, j = random.randrange(N), random.randrange(N)
swapped[i] = True
deck[i], deck[j] = deck[j], deck[i]
def shuffle2a(deck):
# http://forums.udacity.com/cs212-april2012/questions/3462/better-implementation-of-shuffle2
N = len(deck)
swapped = [False] * N
while not all(swapped):
i = random.choice(filter(lambda idx: not swapped[idx], range(N)))
j = random.choice(filter(lambda idx: not swapped[idx], range(N)))
swapped[i] = True
deck[i], deck[j] = deck[j], deck[i]
def shuffle3(deck):
# O(N)
# incorrect distribution
N = len(deck)
for i in range(N):
j = random.randrange(N)
deck[i], deck[j] = deck[j], deck[i]
def shuffle(deck):
# Knuth method
n = len(deck)
for i in range(n-1):
j = random.randrange(i, n)
deck[i], deck[j] = deck[j], deck[i]
def test_shuffler(shuffler, deck='abcd', n=10000):
counts = defaultdict(int)
for _ in range(n):
input = list(deck)
shuffler(input)
counts[''.join(input)] += 1
e = n*1./factorial(len(deck)) ## expected count
ok = all((0.9 <= counts[item]/e <= 1.1) for item in counts)
name = shuffler.__name__
print '%s(%s) %s' % (name, deck, ('ok' if ok else '*** bad ***'))
print ' ',
for item, count in sorted(counts.items()):
print "%s:%4.1f" % (item, count*100./n),
print
def test_shufflers(shufflers=[shuffle, shuffle1], decks=['abc','ab']):
for deck in decks:
print
for f in shufflers:
test_shuffler(f, deck)
def factorial(n): return 1 if (n <= 1) else n*factorial(n-1)
In [19]:
print (7,3)>(7,1) , 'hello'>'hl'
In [26]:
s1="2c 3d".split()