## 2016年11月5日土曜日

### Python - Inheritance(the possible hands in poker, value)

Think Python (Allen B. Downey (著)、 O'Reilly Media)のChapter 18.(Inheritance)のExercises 18-3-4.(No. 4220)を取り組んでみる。

Exercises 18-3-4.(No. 4220)

コード(Emacs)

```#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from Card import Hand, Deck, Card

class PokerHand(Hand):
size = 5

def suit_hist(self):
"""Builds a histogram of the suits that appear in the hand.

Stores the result in attribute suits.
"""
self.suits = {}
for card in self.cards:
self.suits[card.suit] = self.suits.get(card.suit, 0) + 1

def rank_hist(self):
self.ranks = {}
for card in self.cards:
self.ranks[card.rank] = self.ranks.get(card.rank, 0) + 1

def has_flush(self):
"""Returns True if the hand has a flush, False otherwise.

Note that this works correctly for hands with more than 5 cards.
"""
self.suit_hist()
for val in self.suits.values():
if val >= 5:
return True
return False

def has_pair(self):
self.rank_hist()
for val in self.ranks.values():
if val == 2:
return True
return False

def has_twopair(self):
self.rank_hist()
count = 0
for val in self.ranks.values():
if val == 2:
if count == 0:
count = 1
else:
return True
return False

def has_three_of_kind(self):
self.rank_hist()
for val in self.ranks.values():
if val == 3:
return True
return False

def has_straight(self):
self.rank_hist()
ks = self.ranks.keys()
start = 1
stop = 13 - (PokerHand.size - 1) + 1
for n in range(start, stop):
for m in range(n, n + PokerHand.size):
if m not in ks:
break
else:
return True
if 1 in ks:
start = 13 - (PokerHand.size - 1) + 1
stop = start + PokerHand.size - 1
for n in range(start, stop):
if n not in ks:
return False
return True
return False

def has_full_house(self):
return self.has_pair() and self.has_three_of_kind()

def has_four_of_kind(self):
self.rank_hist()
for val in self.ranks.values():
if val == 4:
return True
return False

def has_straight_flush(self):
return self.has_straight() and self.has_flush()

labels = {
'pair': has_pair,
'two pair': has_twopair,
'three of a kind': has_three_of_kind,
'straight': has_straight,
'flush': has_flush,
'full house': has_full_house,
'four of a kind': has_four_of_kind,
'straight flush': has_straight_flush
}

def classify(self):
for k, v in PokerHand.labels.items():
if v(self):
self.label = k

if __name__ == '__main__':
# make a deck
deck = Deck()
deck.shuffle()

# deal the cards and classify the hands
for i in range(7):
hand = PokerHand()
deck.move_cards(hand, 7)
hand.sort()
print(hand)
print('flush: {0}'.format(hand.has_flush()))
print('pair: {0}'.format(hand.has_pair()))
print('two pair: {0}'.format(hand.has_twopair()))
print('three of a kind: {0}'.format(hand.has_three_of_kind()))
print('full house: {0}'.format(hand.has_full_house()))
print('four of a kind: {0}'.format(hand.has_four_of_kind()))
print('straight: {0}'.format(hand.has_straight()))
print('straight flush: {0}'.format(hand.has_straight_flush()))
hand.classify()
print('label: {0}'.format(hand.label))
print('')
```

```\$ ./PokerHand.py
2 of Clubs
3 of Clubs
Ace of Diamonds
7 of Diamonds
7 of Hearts
Jack of Hearts
flush: False
pair: True
two pair: True
three of a kind: False
full house: False
four of a kind: False
straight: False
straight flush: False
label: pair

4 of Clubs
flush: True
pair: True
two pair: False
three of a kind: False
full house: False
four of a kind: False
straight: False
straight flush: False
label: flush

7 of Clubs
3 of Diamonds
8 of Diamonds
Jack of Diamonds
Queen of Diamonds
4 of Hearts
9 of Hearts
flush: False
pair: False
two pair: False
three of a kind: False
full house: False
four of a kind: False
straight: False
straight flush: False
label:

Queen of Clubs
9 of Diamonds
3 of Hearts
8 of Hearts
Queen of Hearts
flush: False
pair: True
two pair: True
three of a kind: False
full house: False
four of a kind: False
straight: False
straight flush: False
label: pair

Ace of Clubs
5 of Clubs
2 of Diamonds
4 of Diamonds
King of Hearts
flush: False
pair: True
two pair: False
three of a kind: False
full house: False
four of a kind: False
straight: False
straight flush: False
label: pair

10 of Clubs
Jack of Clubs
10 of Diamonds
Ace of Hearts
6 of Hearts
10 of Hearts
flush: False
pair: False
two pair: False
three of a kind: True
full house: False
four of a kind: False
straight: False
straight flush: False
label: three of a kind

6 of Clubs
9 of Clubs
King of Clubs
5 of Diamonds
6 of Diamonds
King of Diamonds
5 of Hearts
flush: False
pair: True
two pair: True
three of a kind: False
full house: False
four of a kind: False
straight: False
straight flush: False
label: pair

\$ ./PokerHand.py
5 of Clubs
10 of Clubs
5 of Diamonds
Jack of Diamonds
flush: False
pair: True
two pair: False
three of a kind: False
full house: False
four of a kind: False
straight: False
straight flush: False
label: pair

Ace of Clubs
9 of Clubs
7 of Diamonds
Queen of Diamonds
6 of Hearts
10 of Hearts
flush: False
pair: True
two pair: False
three of a kind: False
full house: False
four of a kind: False
straight: False
straight flush: False
label: pair

3 of Clubs
4 of Clubs
2 of Diamonds
6 of Diamonds
5 of Hearts
flush: False
pair: True
two pair: False
three of a kind: False
full house: False
four of a kind: False
straight: True
straight flush: False
label: pair

8 of Clubs
4 of Diamonds
8 of Diamonds
Ace of Hearts
2 of Hearts
flush: False
pair: True
two pair: False
three of a kind: False
full house: False
four of a kind: False
straight: False
straight flush: False
label: pair

6 of Clubs
Jack of Clubs
10 of Diamonds
3 of Hearts
4 of Hearts
flush: False
pair: True
two pair: False
three of a kind: False
full house: False
four of a kind: False
straight: False
straight flush: False
label: pair

Queen of Clubs
Ace of Diamonds
3 of Diamonds
7 of Hearts
9 of Hearts
King of Hearts
flush: False
pair: True
two pair: False
three of a kind: False
full house: False
four of a kind: False
straight: False
straight flush: False
label: pair

2 of Clubs
7 of Clubs
9 of Diamonds
King of Diamonds
8 of Hearts
Jack of Hearts
Queen of Hearts
flush: False
pair: False
two pair: False
three of a kind: False
full house: False
four of a kind: False
straight: False
straight flush: False
label:

\$
```