Ryan is an engineer in the Sacramento Area with a focus in Python, Ruby, and Rust. Bash/Python Exercism mentor. Coding, physics, calculus, music, woodworking. Looking for work!
This one seemed pretty straightforward, so I knocked it out in Python in an effort to get caught up. I forgot about the "no repeats" rule and stared at my terminal recursing infinitely for a while. Also, deque was a great idea, but I didn't realize you couldn't slice a deque in Python, which made copying them partially a bit awkward.
"""Day 22: Crab Combat
Play a crab in Combat (War) and calculate the score of the winner.
"""fromcollectionsimportdequefromcopyimportdeepcopydefparse(filename):"""Parses the input file into a list of players numbers. Input file
has the format:
Player 1:
1
2
3
Player 2:
4
5
6
Supports arbitrary numbers of players.
"""players=[deque()]current=0withopen(filename,"r")asf:forlineinf:line=line.strip()ifline.isnumeric():players[current].append(int(line))continueifnotline:current+=1players.append(deque())returnplayersdefpart1(players):"""Simulate a game of war and then calculate the score of the
winner.
"""whileall(playerforplayerinplayers):plays=[player.popleft()forplayerinplayers]winner=max((value,ind)for(ind,value)inenumerate(plays))players[winner[1]].extend(sorted(plays,reverse=True))returnmax(calculate_score(player)forplayerinplayers)defrecursive_war(p1,p2):"""Recursive war follows these rules:
1. If a particular configuration has been seen before in a game,
Player 1 automatically wins.
2. Otherwise, if either player's number is greater than the number
of cards they have, the player with the highest number wins.
3. Otherwise, the winner is the winner of a sub-game, where
players play with the 1-nth cards in their deck where n is the
value of their 0th card.
Subgames do not affect parent games' decks (i.e. they are played
with copies).
Returns the calculated score of the winner of the root game's deck.
Not designed for arbitrary #'s of players. Only two.
"""seen=set()whilep1andp2:ifstr(p1)+str(p2)inseen:return0,calculate_score(p1)else:seen.add(str(p1)+str(p2))v1,v2=p1.popleft(),p2.popleft()ifv1<=len(p1)andv2<=len(p2):winner,_score=recursive_war(deque(list(p1)[:v1]),deque(list(p2)[:v2]))else:winner=0ifv1>v2else1ifwinner==0:p1.extend([v1,v2])else:p2.extend([v2,v1])ifp1:return0,calculate_score(p1)else:return1,calculate_score(p2)defcalculate_score(player):"""Calculate the "score" of a player's deck. Their bottom card
times 1 plus their second bottom card times 2 plus ...
"""returnsum(val*indforind,valinenumerate(reversed(player),start=1))defpart2(players):"""Calculate the score of a winner of recursive War."""winner,score=recursive_war(*players)returnscoreif__name__=="__main__":players=parse("data/day22_test.txt")assertpart1(deepcopy(players))==306assertpart2(players)==291print("All tests passed!")players=parse("data/day22.txt")print("Part 1: ",part1(deepcopy(players)))print("Part 2: ",part2(players))
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
This one seemed pretty straightforward, so I knocked it out in Python in an effort to get caught up. I forgot about the "no repeats" rule and stared at my terminal recursing infinitely for a while. Also,
deque
was a great idea, but I didn't realize you couldn't slice adeque
in Python, which made copying them partially a bit awkward.