Dazbo's Advent of Code solutions, written in Python
We’re told we’re going to play Rock, Paper, Scissors with the elves. But we’ve been given a piece of paper that tells us what our opponent will do, and what we should do!
Our input data contains many lines, with each line having two columns.
The input data looks something like this:
A Y
B X
C Z
For each hand we play, our score is the sum of the following:
Our total score is the sum of the scores for all the hands we play.
Treat the second column as what we must play. X=Rock, Y=Paper, Z=Scissors
What is our final score?
To be honest, the code is so trivial it hardly needs explaining. Must of how it works is documented in the code itself.
Here it is…
from pathlib import Path
import time
HAND = {
"ROCK": "A",
"PAPER": "B",
"SCISSORS": "C"
}
SCORES = {
HAND["ROCK"]: 1,
HAND["PAPER"]: 2,
HAND["SCISSORS"]: 3,
"LOSE": 0,
"DRAW": 3,
"WIN": 6
}
RULES = {
# (Their hand, my hand)
(HAND["ROCK"], HAND["SCISSORS"]): SCORES["LOSE"],
(HAND["ROCK"], HAND["ROCK"]): SCORES["DRAW"],
(HAND["ROCK"], HAND["PAPER"]): SCORES["WIN"],
(HAND["PAPER"], HAND["ROCK"]): SCORES["LOSE"],
(HAND["PAPER"], HAND["PAPER"]): SCORES["DRAW"],
(HAND["PAPER"], HAND["SCISSORS"]): SCORES["WIN"],
(HAND["SCISSORS"], HAND["PAPER"]): SCORES["LOSE"],
(HAND["SCISSORS"], HAND["SCISSORS"]): SCORES["DRAW"],
(HAND["SCISSORS"], HAND["ROCK"]): SCORES["WIN"]
}
SCRIPT_DIR = Path(__file__).parent
INPUT_FILE = Path(SCRIPT_DIR, "input/input.txt")
def main():
with open(INPUT_FILE, mode="rt") as f:
data = f.read().splitlines()
# Part 1
rounds = play_rounds(data)
scores = play_part_1(rounds)
print(f"Part 1: Your score = {sum(scores)}")
def play_part_1(rounds: list):
""" Here we treat X, Y, Z as whether we play Rock, Paper, Scissors, respectively.
Calculate our score for each hand based on what hand we play, and whether we win, lose or draw. """
scores = []
zyz_to_rps = {"X": HAND["ROCK"], "Y": HAND["PAPER"], "Z": HAND["SCISSORS"]}
for this_round in rounds:
their_hand, my_hand = this_round
my_hand = zyz_to_rps[my_hand]
this_score = 0
this_score += SCORES[my_hand]
this_score += RULES[(their_hand, my_hand)]
scores.append(this_score)
return scores
def play_rounds(data: list[str]) -> list:
""" Returns a list. Each element in the list is a pair as a list, e.g. ["A", "X"] """
rounds = []
for this_round in data:
rounds.append(this_round.split())
return rounds
if __name__ == "__main__":
t1 = time.perf_counter()
main()
t2 = time.perf_counter()
print(f"Execution time: {t2 - t1:0.4f} seconds")
list
, where each list item is itself a pair of items. The first item in the pair - i.e. this_round[0]
- is what our opponent did. The second item - i.e. this_round[1]
- is what we must do.if... elif... else
statements.Now, we must treat the second column as the outcome required. X=Lose, Y=Draw, Z=Win
What is our final score?
Okay, so we need to extend our rules…
REQUIRED = {
"LOSE": "X",
"DRAW": "Y",
"WIN": "Z"
}
RULES = {
# (Their hand, my hand): score
(HAND["ROCK"], HAND["SCISSORS"]): SCORES["LOSE"],
(HAND["ROCK"], HAND["ROCK"]): SCORES["DRAW"],
(HAND["ROCK"], HAND["PAPER"]): SCORES["WIN"],
(HAND["PAPER"], HAND["ROCK"]): SCORES["LOSE"],
(HAND["PAPER"], HAND["PAPER"]): SCORES["DRAW"],
(HAND["PAPER"], HAND["SCISSORS"]): SCORES["WIN"],
(HAND["SCISSORS"], HAND["PAPER"]): SCORES["LOSE"],
(HAND["SCISSORS"], HAND["SCISSORS"]): SCORES["DRAW"],
(HAND["SCISSORS"], HAND["ROCK"]): SCORES["WIN"],
# (Their hand, my goal): score-for-my-hand
(HAND["ROCK"], REQUIRED["LOSE"]): SCORES[HAND["SCISSORS"]],
(HAND["ROCK"], REQUIRED["DRAW"]): SCORES[HAND["ROCK"]],
(HAND["ROCK"], REQUIRED["WIN"]): SCORES[HAND["PAPER"]],
(HAND["PAPER"], REQUIRED["LOSE"]): SCORES[HAND["ROCK"]],
(HAND["PAPER"], REQUIRED["DRAW"]): SCORES[HAND["PAPER"]],
(HAND["PAPER"], REQUIRED["WIN"]): SCORES[HAND["SCISSORS"]],
(HAND["SCISSORS"], REQUIRED["LOSE"]): SCORES[HAND["PAPER"]],
(HAND["SCISSORS"], REQUIRED["DRAW"]): SCORES[HAND["SCISSORS"]],
(HAND["SCISSORS"], REQUIRED["WIN"]): SCORES[HAND["ROCK"]]
}
And then we just add a new function to apply the new rules:
def play_part_2(rounds: list):
""" Here we treat X, Y, Z as whether we play Lose, Draw, or Win, respectively.
Determine what hand we should play to achieve that outcome.
Then calculate our score for each hand based on what hand we chose, and whether we win, lose or draw. """
scores = []
xyz_to_ldw = {"X": SCORES["LOSE"], "Y": SCORES["DRAW"], "Z": SCORES["WIN"]}
for this_round in rounds:
their_hand, my_goal = this_round
this_score = 0
this_score += xyz_to_ldw[my_goal]
this_score += RULES[(their_hand, my_goal)]
scores.append(this_score)
return scores
And then add this to our main
method:
scores = play_part_2(rounds)
print(f"Part 2: Your score = {sum(scores)}")
The output looks like this:
Part 1: Your score = 13221
Part 2: Your score = 13131
Execution time: 0.0017 seconds