Commit 6c4c2abe authored by Bryan Jennings's avatar Bryan Jennings Committed by Donne Martin
Browse files

Simplify logic for is_ace and is_face_card in deck of cards solution (#113)

parent 2aa2166b
...@@ -89,11 +89,11 @@ ...@@ -89,11 +89,11 @@
" super(BlackJackCard, self).__init__(value, suit)\n", " super(BlackJackCard, self).__init__(value, suit)\n",
"\n", "\n",
" def is_ace(self):\n", " def is_ace(self):\n",
" return True if self._value == 1 else False\n", " return self._value == 1\n",
"\n", "\n",
" def is_face_card(self):\n", " def is_face_card(self):\n",
" \"\"\"Jack = 11, Queen = 12, King = 13\"\"\"\n", " \"\"\"Jack = 11, Queen = 12, King = 13\"\"\"\n",
" return True if 10 < self._value <= 13 else False\n", " return 10 < self._value <= 13\n",
"\n", "\n",
" @property\n", " @property\n",
" def value(self):\n", " def value(self):\n",
......
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
This notebook was prepared by [Donne Martin](https://github.com/donnemartin). Source and license info is on [GitHub](https://github.com/donnemartin/system-design-primer-primer). This notebook was prepared by [Donne Martin](https://github.com/donnemartin). Source and license info is on [GitHub](https://github.com/donnemartin/system-design-primer-primer).
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# Design a deck of cards # Design a deck of cards
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Constraints and assumptions ## Constraints and assumptions
* Is this a generic deck of cards for games like poker and black jack? * Is this a generic deck of cards for games like poker and black jack?
* Yes, design a generic deck then extend it to black jack * Yes, design a generic deck then extend it to black jack
* Can we assume the deck has 52 cards (2-10, Jack, Queen, King, Ace) and 4 suits? * Can we assume the deck has 52 cards (2-10, Jack, Queen, King, Ace) and 4 suits?
* Yes * Yes
* Can we assume inputs are valid or do we have to validate them? * Can we assume inputs are valid or do we have to validate them?
* Assume they're valid * Assume they're valid
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Solution ## Solution
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
%%writefile deck_of_cards.py %%writefile deck_of_cards.py
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from enum import Enum from enum import Enum
import sys import sys
class Suit(Enum): class Suit(Enum):
HEART = 0 HEART = 0
DIAMOND = 1 DIAMOND = 1
CLUBS = 2 CLUBS = 2
SPADE = 3 SPADE = 3
class Card(metaclass=ABCMeta): class Card(metaclass=ABCMeta):
def __init__(self, value, suit): def __init__(self, value, suit):
self.value = value self.value = value
self.suit = suit self.suit = suit
self.is_available = True self.is_available = True
@property @property
@abstractmethod @abstractmethod
def value(self): def value(self):
pass pass
@value.setter @value.setter
@abstractmethod @abstractmethod
def value(self, other): def value(self, other):
pass pass
class BlackJackCard(Card): class BlackJackCard(Card):
def __init__(self, value, suit): def __init__(self, value, suit):
super(BlackJackCard, self).__init__(value, suit) super(BlackJackCard, self).__init__(value, suit)
def is_ace(self): def is_ace(self):
return True if self._value == 1 else False return self._value == 1
def is_face_card(self): def is_face_card(self):
"""Jack = 11, Queen = 12, King = 13""" """Jack = 11, Queen = 12, King = 13"""
return True if 10 < self._value <= 13 else False return 10 < self._value <= 13
@property @property
def value(self): def value(self):
if self.is_ace() == 1: if self.is_ace() == 1:
return 1 return 1
elif self.is_face_card(): elif self.is_face_card():
return 10 return 10
else: else:
return self._value return self._value
@value.setter @value.setter
def value(self, new_value): def value(self, new_value):
if 1 <= new_value <= 13: if 1 <= new_value <= 13:
self._value = new_value self._value = new_value
else: else:
raise ValueError('Invalid card value: {}'.format(new_value)) raise ValueError('Invalid card value: {}'.format(new_value))
class Hand(object): class Hand(object):
def __init__(self, cards): def __init__(self, cards):
self.cards = cards self.cards = cards
def add_card(self, card): def add_card(self, card):
self.cards.append(card) self.cards.append(card)
def score(self): def score(self):
total_value = 0 total_value = 0
for card in card: for card in card:
total_value += card.value total_value += card.value
return total_value return total_value
class BlackJackHand(Hand): class BlackJackHand(Hand):
BLACKJACK = 21 BLACKJACK = 21
def __init__(self, cards): def __init__(self, cards):
super(BlackJackHand, self).__init__(cards) super(BlackJackHand, self).__init__(cards)
def score(self): def score(self):
min_over = sys.MAXSIZE min_over = sys.MAXSIZE
max_under = -sys.MAXSIZE max_under = -sys.MAXSIZE
for score in self.possible_scores(): for score in self.possible_scores():
if self.BLACKJACK < score < min_over: if self.BLACKJACK < score < min_over:
min_over = score min_over = score
elif max_under < score <= self.BLACKJACK: elif max_under < score <= self.BLACKJACK:
max_under = score max_under = score
return max_under if max_under != -sys.MAXSIZE else min_over return max_under if max_under != -sys.MAXSIZE else min_over
def possible_scores(self): def possible_scores(self):
"""Return a list of possible scores, taking Aces into account.""" """Return a list of possible scores, taking Aces into account."""
# ... # ...
class Deck(object): class Deck(object):
def __init__(self, cards): def __init__(self, cards):
self.cards = cards self.cards = cards
self.deal_index = 0 self.deal_index = 0
def remaining_cards(self): def remaining_cards(self):
return len(self.cards) - deal_index return len(self.cards) - deal_index
def deal_card(): def deal_card():
try: try:
card = self.cards[self.deal_index] card = self.cards[self.deal_index]
card.is_available = False card.is_available = False
self.deal_index += 1 self.deal_index += 1
except IndexError: except IndexError:
return None return None
return card return card
def shuffle(self): # ... def shuffle(self): # ...
``` ```
%%%% Output: stream %%%% Output: stream
Overwriting deck_of_cards.py Overwriting deck_of_cards.py
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment