2017-03-04 05:51:00 +03:00
{
" cells " : [
{
" cell_type " : " markdown " ,
" metadata " : { } ,
" source " : [
" 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 " ,
" metadata " : { } ,
" source " : [
" # Design a deck of cards "
]
} ,
{
" cell_type " : " markdown " ,
" metadata " : { } ,
" source " : [
" ## Constraints and assumptions \n " ,
" \n " ,
" * Is this a generic deck of cards for games like poker and black jack? \n " ,
" * Yes, design a generic deck then extend it to black jack \n " ,
" * Can we assume the deck has 52 cards (2-10, Jack, Queen, King, Ace) and 4 suits? \n " ,
" * Yes \n " ,
" * Can we assume inputs are valid or do we have to validate them? \n " ,
" * Assume they ' re valid "
]
} ,
{
" cell_type " : " markdown " ,
" metadata " : { } ,
" source " : [
" ## Solution "
]
} ,
{
" cell_type " : " code " ,
" execution_count " : 1 ,
" metadata " : {
" collapsed " : false
} ,
" outputs " : [
{
" name " : " stdout " ,
" output_type " : " stream " ,
" text " : [
" Overwriting deck_of_cards.py \n "
]
}
] ,
" source " : [
" %% writefile deck_of_cards.py \n " ,
" from abc import ABCMeta, abstractmethod \n " ,
" from enum import Enum \n " ,
" import sys \n " ,
" \n " ,
" \n " ,
" class Suit(Enum): \n " ,
" \n " ,
" HEART = 0 \n " ,
" DIAMOND = 1 \n " ,
" CLUBS = 2 \n " ,
" SPADE = 3 \n " ,
" \n " ,
" \n " ,
" class Card(metaclass=ABCMeta): \n " ,
" \n " ,
" def __init__(self, value, suit): \n " ,
" self.value = value \n " ,
" self.suit = suit \n " ,
" self.is_available = True \n " ,
" \n " ,
" @property \n " ,
" @abstractmethod \n " ,
" def value(self): \n " ,
" pass \n " ,
" \n " ,
" @value.setter \n " ,
" @abstractmethod \n " ,
" def value(self, other): \n " ,
" pass \n " ,
" \n " ,
" \n " ,
" class BlackJackCard(Card): \n " ,
" \n " ,
" def __init__(self, value, suit): \n " ,
" super(BlackJackCard, self).__init__(value, suit) \n " ,
" \n " ,
" def is_ace(self): \n " ,
2017-10-25 04:05:59 +03:00
" return self._value == 1 \n " ,
2017-03-04 05:51:00 +03:00
" \n " ,
" def is_face_card(self): \n " ,
" \" \" \" Jack = 11, Queen = 12, King = 13 \" \" \" \n " ,
2017-10-25 04:05:59 +03:00
" return 10 < self._value <= 13 \n " ,
2017-03-04 05:51:00 +03:00
" \n " ,
" @property \n " ,
" def value(self): \n " ,
" if self.is_ace() == 1: \n " ,
" return 1 \n " ,
" elif self.is_face_card(): \n " ,
" return 10 \n " ,
" else: \n " ,
" return self._value \n " ,
" \n " ,
" @value.setter \n " ,
" def value(self, new_value): \n " ,
" if 1 <= new_value <= 13: \n " ,
" self._value = new_value \n " ,
" else: \n " ,
" raise ValueError( ' Invalid card value: {} ' .format(new_value)) \n " ,
" \n " ,
" \n " ,
" class Hand(object): \n " ,
" \n " ,
" def __init__(self, cards): \n " ,
" self.cards = cards \n " ,
" \n " ,
" def add_card(self, card): \n " ,
" self.cards.append(card) \n " ,
" \n " ,
" def score(self): \n " ,
" total_value = 0 \n " ,
" for card in card: \n " ,
" total_value += card.value \n " ,
" return total_value \n " ,
" \n " ,
" \n " ,
" class BlackJackHand(Hand): \n " ,
" \n " ,
" BLACKJACK = 21 \n " ,
" \n " ,
" def __init__(self, cards): \n " ,
" super(BlackJackHand, self).__init__(cards) \n " ,
" \n " ,
" def score(self): \n " ,
" min_over = sys.MAXSIZE \n " ,
" max_under = -sys.MAXSIZE \n " ,
" for score in self.possible_scores(): \n " ,
" if self.BLACKJACK < score < min_over: \n " ,
" min_over = score \n " ,
" elif max_under < score <= self.BLACKJACK: \n " ,
" max_under = score \n " ,
" return max_under if max_under != -sys.MAXSIZE else min_over \n " ,
" \n " ,
" def possible_scores(self): \n " ,
" \" \" \" Return a list of possible scores, taking Aces into account. \" \" \" \n " ,
" # ... \n " ,
" \n " ,
" \n " ,
" class Deck(object): \n " ,
" \n " ,
" def __init__(self, cards): \n " ,
" self.cards = cards \n " ,
" self.deal_index = 0 \n " ,
" \n " ,
" def remaining_cards(self): \n " ,
" return len(self.cards) - deal_index \n " ,
" \n " ,
" def deal_card(): \n " ,
" try: \n " ,
" card = self.cards[self.deal_index] \n " ,
" card.is_available = False \n " ,
" self.deal_index += 1 \n " ,
" except IndexError: \n " ,
" return None \n " ,
" return card \n " ,
" \n " ,
" def shuffle(self): # ... "
]
}
] ,
" metadata " : {
" kernelspec " : {
" display_name " : " Python 3 " ,
" language " : " python " ,
" name " : " python3 "
} ,
" language_info " : {
" codemirror_mode " : {
" name " : " ipython " ,
" version " : 3
} ,
" file_extension " : " .py " ,
" mimetype " : " text/x-python " ,
" name " : " python " ,
" nbconvert_exporter " : " python " ,
" pygments_lexer " : " ipython3 " ,
" version " : " 3.4.3 "
}
} ,
" nbformat " : 4 ,
" nbformat_minor " : 0
}