Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # war.py
- from sys import argv
- from collections import deque
- def read_in_match_data(filepath='challenge_inputs.txt'):
- with open(filepath, 'r') as f:
- challenges = []
- odd_line = []
- for index, line in enumerate(f.readlines()):
- parsed_line = list(line.strip().split(' '))
- if index % 2 == 0:
- odd_line = parsed_line
- else:
- challenges.append((odd_line, parsed_line))
- return challenges
- class EmptyHand(Exception):
- def __init__(self, value=None):
- error_message = 'there are no cards in this hand'
- self.value = value if value is not None else error_message
- def __str__(self):
- return repr(self.value)
- class NotEnoughCardsInHand(Exception):
- def __init__(self, value=None):
- error_message = 'not enough cards in this hand'
- self.value = value if value is not None else error_message
- def __str__(self):
- return repr(self.value)
- class Hand:
- def __init__(self, card_list=None):
- self.cards = deque()
- self.record = {
- 'wins': [],
- 'losses': []
- }
- cards = card_list if card_list else []
- self.add_cards(cards)
- def add_cards(self, cards):
- # TODO: validate cards list items, handle out of range values for the card elements
- try:
- self.cards.extend(cards)
- except TypeError:
- self.cards.append(cards)
- def draw(self, num=1):
- if len(self.cards) < num:
- raise NotEnoughCardsInHand
- return [self.cards.popleft() for i in range(num)]
- class Match:
- def __init__(self, player_a, player_b):
- if not isinstance(player_a, Hand) and isinstance(player_b, Hand):
- raise TypeError('Match only accepts Hand objects')
- self.player_a = player_a
- self.player_b = player_b
- self.round = 0
- def simulate_match(self):
- while self.player_a.cards and self.player_b.cards:
- self.next_round()
- a_len = len(self.player_a.cards)
- b_len = len(self.player_b.cards)
- res = 0
- if a_len > b_len:
- res = 1
- elif a_len < b_len:
- res = 2
- return res
- def next_round(self):
- self.round += 1
- a = self.player_a.draw()
- b = self.player_b.draw()
- winnings = a + b
- if a == b:
- self.war(winnings)
- elif a > b:
- self.player_a.add_cards(winnings)
- else:
- self.player_b.add_cards(winnings)
- def war(self, existing_pile):
- a_len = len(self.player_a.cards)
- b_len = len(self.player_b.cards)
- if a_len == b_len == 0:
- return # this means the game is a tie
- to_draw = 3
- if a_len < 4 or b_len < 4:
- less = len(self.player_a.cards) if a_len < b_len else len(self.player_b.cards)
- to_draw = less - 1
- hidden = self.player_a.draw(to_draw) + self.player_b.draw(to_draw)
- a = self.player_a.draw()
- b = self.player_b.draw()
- winnings = existing_pile + hidden + a + b
- if a == b:
- self.war(winnings)
- elif a > b:
- self.player_a.add_cards(winnings)
- else:
- self.player_b.add_cards(winnings)
- if __name__ == '__main__':
- matchups = read_in_match_data()
- if len(argv) == 2:
- matchups = read_in_match_data(filepath=argv[1])
- for matchup in matchups:
- player_a_card_list, player_b_card_list = matchup
- a = Hand(player_a_card_list)
- b = Hand(player_b_card_list)
- print(Match(a, b).simulate_match())
- # --------
- # test_war.py
- import pytest
- import war
- def test_read_in_match_data():
- assert isinstance(war.read_in_match_data(), list)
- def test_read_in_ignores_last_odd_line():
- res = war.read_in_match_data(filepath='test_input_data.txt')
- assert len(res) == 2
- def test_hand_initial():
- h = war.Hand([1, 2, 3, 4, 5])
- assert len(h.cards) == 5
- assert len(h.record['wins']) == len(h.record['losses']) == 0
- h1 = war.Hand()
- assert len(h1.cards) == 0
- assert len(h1.record['wins']) == len(h1.record['losses']) == 0
- def test_add_single_card():
- h = war.Hand([1, 2, 3, 4, 5, 6])
- h.add_cards(14)
- assert 14 in h.cards
- def test_add_cards_to_empty():
- h = war.Hand()
- to_add = [13, 11, 9]
- h.add_cards(to_add)
- assert len(h.cards) == len(to_add)
- for c in to_add:
- assert c in h.cards
- def test_add_cards_to_existing():
- starting = [1, 2, 3, 4, 5]
- h = war.Hand(starting)
- to_add = [12, 12, 12]
- h.add_cards(to_add)
- assert len(h.cards) == len(starting) + len(to_add)
- def test_draw_zero_cards():
- h = war.Hand([1])
- h.draw(0)
- assert len(h.cards) == 1
- def test_draw_single_card():
- h = war.Hand([1, 2, 3])
- c = h.draw()
- assert c == [1]
- assert len(h.cards) == 2
- def test_draw_three_cards():
- h = war.Hand([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
- drawn_cards = h.draw(3)
- assert len(drawn_cards) == 3
- assert drawn_cards == [1, 2, 3]
- assert len(h.cards) == 7
- def test_draw_negative_cards_doesnt_change_deck():
- card_list = [1, 2, 3, 4, 5]
- h = war.Hand(card_list)
- h.draw(-1)
- assert len(card_list) == len(h.cards)
- def test_draw_negative_cards_and_zero_cards_against_empty_deck():
- h = war.Hand()
- drawn = h.draw(-1)
- assert not drawn
- h.draw(0)
- assert len(h.cards) == 0
- with pytest.raises(war.NotEnoughCardsInHand):
- h.draw()
- def test_draw_too_many_cards():
- h = war.Hand()
- h.add_cards([1, 2])
- with pytest.raises(war.NotEnoughCardsInHand):
- h.draw(3)
- def test_match_init():
- with pytest.raises(TypeError):
- war.Match()
- war.Match([1, 2, 3], 'fuck you')
- m = war.Match(war.Hand([1, 2, 3]), war.Hand([4, 3, 2]))
- assert m.round == 0
- assert isinstance(m.player_a, war.Hand)
- assert isinstance(m.player_b, war.Hand)
- def test_match_round():
- p1 = war.Hand([1, 9, 2])
- p2 = war.Hand([9, 2])
- m = war.Match(p1, p2)
- p1_card_count = len(p1.cards)
- p2_card_count = len(p2.cards)
- m.next_round()
- assert len(p1.cards) == p1_card_count - 1
- assert len(p2.cards) == p2_card_count + 1
- def test_match_war():
- p1 = war.Hand([1, 9, 2, 9, 1, 3, 1])
- p2 = war.Hand([1, 8, 7, 5, 3, 2, 2])
- m = war.Match(p1, p2)
- p1_card_count = len(p1.cards)
- p2_card_count = len(p2.cards)
- m.next_round()
- assert len(p1.cards) == p1_card_count - 5
- assert len(p2.cards) == p2_card_count + 5
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement