Advertisement
Guest User

r/daily_programmer 320 war

a guest
Jun 27th, 2017
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.74 KB | None | 0 0
  1. # war.py
  2. from sys import argv
  3. from collections import deque
  4.  
  5.  
  6. def read_in_match_data(filepath='challenge_inputs.txt'):
  7.     with open(filepath, 'r') as f:
  8.         challenges = []
  9.         odd_line = []
  10.         for index, line in enumerate(f.readlines()):
  11.             parsed_line = list(line.strip().split(' '))
  12.             if index % 2 == 0:
  13.                 odd_line = parsed_line
  14.             else:
  15.                 challenges.append((odd_line, parsed_line))
  16.  
  17.     return challenges
  18.  
  19.  
  20. class EmptyHand(Exception):
  21.     def __init__(self, value=None):
  22.         error_message = 'there are no cards in this hand'
  23.         self.value = value if value is not None else error_message
  24.  
  25.     def __str__(self):
  26.         return repr(self.value)
  27.  
  28.  
  29. class NotEnoughCardsInHand(Exception):
  30.     def __init__(self, value=None):
  31.         error_message = 'not enough cards in this hand'
  32.         self.value = value if value is not None else error_message
  33.  
  34.     def __str__(self):
  35.         return repr(self.value)
  36.  
  37.  
  38. class Hand:
  39.     def __init__(self, card_list=None):
  40.         self.cards = deque()
  41.         self.record = {
  42.                 'wins': [],
  43.                 'losses': []
  44.                 }
  45.  
  46.         cards = card_list if card_list else []
  47.         self.add_cards(cards)
  48.  
  49.     def add_cards(self, cards):
  50.         # TODO: validate cards list items, handle out of range values for the card elements
  51.         try:
  52.             self.cards.extend(cards)
  53.         except TypeError:
  54.             self.cards.append(cards)
  55.  
  56.     def draw(self, num=1):
  57.         if len(self.cards) < num:
  58.             raise NotEnoughCardsInHand
  59.  
  60.         return [self.cards.popleft() for i in range(num)]
  61.  
  62.  
  63. class Match:
  64.     def __init__(self, player_a, player_b):
  65.         if not isinstance(player_a, Hand) and isinstance(player_b, Hand):
  66.             raise TypeError('Match only accepts Hand objects')
  67.         self.player_a = player_a
  68.         self.player_b = player_b
  69.         self.round = 0
  70.  
  71.     def simulate_match(self):
  72.         while self.player_a.cards and self.player_b.cards:
  73.             self.next_round()
  74.  
  75.         a_len = len(self.player_a.cards)
  76.         b_len = len(self.player_b.cards)
  77.  
  78.         res = 0
  79.         if a_len > b_len:
  80.             res = 1
  81.         elif a_len < b_len:
  82.             res = 2
  83.  
  84.         return res
  85.  
  86.     def next_round(self):
  87.         self.round += 1
  88.         a = self.player_a.draw()
  89.         b = self.player_b.draw()
  90.         winnings = a + b
  91.  
  92.         if a == b:
  93.             self.war(winnings)
  94.         elif a > b:
  95.             self.player_a.add_cards(winnings)
  96.         else:
  97.             self.player_b.add_cards(winnings)
  98.  
  99.     def war(self, existing_pile):
  100.         a_len = len(self.player_a.cards)
  101.         b_len = len(self.player_b.cards)
  102.         if a_len == b_len == 0:
  103.             return  # this means the game is a tie
  104.  
  105.         to_draw = 3
  106.         if a_len < 4 or b_len < 4:
  107.             less = len(self.player_a.cards) if a_len < b_len else len(self.player_b.cards)
  108.             to_draw = less - 1
  109.  
  110.         hidden = self.player_a.draw(to_draw) + self.player_b.draw(to_draw)
  111.  
  112.         a = self.player_a.draw()
  113.         b = self.player_b.draw()
  114.         winnings = existing_pile + hidden + a + b
  115.  
  116.         if a == b:
  117.             self.war(winnings)
  118.         elif a > b:
  119.             self.player_a.add_cards(winnings)
  120.         else:
  121.             self.player_b.add_cards(winnings)
  122.  
  123.  
  124. if __name__ == '__main__':
  125.     matchups = read_in_match_data()
  126.  
  127.     if len(argv) == 2:
  128.         matchups = read_in_match_data(filepath=argv[1])
  129.  
  130.     for matchup in matchups:
  131.         player_a_card_list, player_b_card_list = matchup
  132.         a = Hand(player_a_card_list)
  133.         b = Hand(player_b_card_list)
  134.         print(Match(a, b).simulate_match())
  135.  
  136.  
  137. # --------
  138. # test_war.py
  139.  
  140. import pytest
  141.  
  142. import war
  143.  
  144.  
  145. def test_read_in_match_data():
  146.     assert isinstance(war.read_in_match_data(), list)
  147.  
  148.  
  149. def test_read_in_ignores_last_odd_line():
  150.     res = war.read_in_match_data(filepath='test_input_data.txt')
  151.     assert len(res) == 2
  152.  
  153.  
  154. def test_hand_initial():
  155.         h = war.Hand([1, 2, 3, 4, 5])
  156.         assert len(h.cards) == 5
  157.         assert len(h.record['wins']) == len(h.record['losses']) == 0
  158.  
  159.         h1 = war.Hand()
  160.         assert len(h1.cards) == 0
  161.         assert len(h1.record['wins']) == len(h1.record['losses']) == 0
  162.  
  163.  
  164. def test_add_single_card():
  165.     h = war.Hand([1, 2, 3, 4, 5, 6])
  166.     h.add_cards(14)
  167.     assert 14 in h.cards
  168.  
  169.  
  170. def test_add_cards_to_empty():
  171.     h = war.Hand()
  172.     to_add = [13, 11, 9]
  173.     h.add_cards(to_add)
  174.     assert len(h.cards) == len(to_add)
  175.  
  176.     for c in to_add:
  177.         assert c in h.cards
  178.  
  179.  
  180. def test_add_cards_to_existing():
  181.     starting = [1, 2, 3, 4, 5]
  182.     h = war.Hand(starting)
  183.     to_add = [12, 12, 12]
  184.     h.add_cards(to_add)
  185.     assert len(h.cards) == len(starting) + len(to_add)
  186.  
  187.  
  188. def test_draw_zero_cards():
  189.     h = war.Hand([1])
  190.     h.draw(0)
  191.     assert len(h.cards) == 1
  192.  
  193.  
  194. def test_draw_single_card():
  195.     h = war.Hand([1, 2, 3])
  196.     c = h.draw()
  197.     assert c == [1]
  198.     assert len(h.cards) == 2
  199.  
  200.  
  201. def test_draw_three_cards():
  202.     h = war.Hand([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
  203.     drawn_cards = h.draw(3)
  204.     assert len(drawn_cards) == 3
  205.     assert drawn_cards == [1, 2, 3]
  206.     assert len(h.cards) == 7
  207.  
  208.  
  209. def test_draw_negative_cards_doesnt_change_deck():
  210.     card_list = [1, 2, 3, 4, 5]
  211.     h = war.Hand(card_list)
  212.     h.draw(-1)
  213.     assert len(card_list) == len(h.cards)
  214.  
  215.  
  216. def test_draw_negative_cards_and_zero_cards_against_empty_deck():
  217.     h = war.Hand()
  218.     drawn = h.draw(-1)
  219.     assert not drawn
  220.  
  221.     h.draw(0)
  222.     assert len(h.cards) == 0
  223.  
  224.     with pytest.raises(war.NotEnoughCardsInHand):
  225.         h.draw()
  226.  
  227.  
  228. def test_draw_too_many_cards():
  229.     h = war.Hand()
  230.     h.add_cards([1, 2])
  231.     with pytest.raises(war.NotEnoughCardsInHand):
  232.         h.draw(3)
  233.  
  234.  
  235. def test_match_init():
  236.     with pytest.raises(TypeError):
  237.         war.Match()
  238.         war.Match([1, 2, 3], 'fuck you')
  239.  
  240.     m = war.Match(war.Hand([1, 2, 3]), war.Hand([4, 3, 2]))
  241.     assert m.round == 0
  242.     assert isinstance(m.player_a, war.Hand)
  243.     assert isinstance(m.player_b, war.Hand)
  244.  
  245.  
  246. def test_match_round():
  247.     p1 = war.Hand([1, 9, 2])
  248.     p2 = war.Hand([9, 2])
  249.     m = war.Match(p1, p2)
  250.  
  251.     p1_card_count = len(p1.cards)
  252.     p2_card_count = len(p2.cards)
  253.  
  254.     m.next_round()
  255.     assert len(p1.cards) == p1_card_count - 1
  256.     assert len(p2.cards) == p2_card_count + 1
  257.  
  258.  
  259. def test_match_war():
  260.     p1 = war.Hand([1, 9, 2, 9, 1, 3, 1])
  261.     p2 = war.Hand([1, 8, 7, 5, 3, 2, 2])
  262.     m = war.Match(p1, p2)
  263.  
  264.     p1_card_count = len(p1.cards)
  265.     p2_card_count = len(p2.cards)
  266.  
  267.     m.next_round()
  268.     assert len(p1.cards) == p1_card_count - 5
  269.     assert len(p2.cards) == p2_card_count + 5
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement