« posts | «« home

Day 2: Rock Paper Scissors

View puzzle page »

Skip to the code?

If you’d like to read my solution first, the code is available on GitHub.

Puzzle 1

Today’s puzzle input is a two-column series of A, B, or C in the first column and X, Y, or Z in the second column. The input can also be thought of a series of letter pairs (horizontal, rather than vertical).

The letters correspond to rock (A, X), paper (B, Y), and scissors (C, Z) and the input is a proposed sequence of response pairs (your suggested choice is column 2). The goal of the puzzle is to determine the total score you would achieve if you played out this sequence. There are other concerns discussed in the puzzle but we can strip it back to it’s simplest form.

What we know:


Each letter pair can be reduced to a score so we just need a convenient way to store the pairs and their scores so we can look them up. A dictionary of tuples works as a neat representation that we can query using the sequence of pairs from the input.

scores = {
    ('A', 'X'): 4,
    ('B', 'X'): 1,
    ('C', 'X'): 7,
    ('A', 'Y'): 8,
    ('B', 'Y'): 5,
    ('C', 'Y'): 2,
    ('A', 'Z'): 3,
    ('B', 'Z'): 9,
    ('C', 'Z'): 6,

For the pair ('A', 'X'), we’re pitting rock against rock which is a draw. Playing rock earns 1 point and a draw earns 3 so the pairing scores 4. ('B', 'Z') pits paper against scissors. The win scores 6 and playing scissors earns 3 so that pairing scores 9.

We’re using tuples to store the pair instead of lists because lists are not hashable objects.

This mapping is the hard work for this puzzle. We can re-use our with context and for loop from day 1’s solution to iterate through the contents of the input.

with open("day2_input.txt", encoding="utf-8") as f:
    for line in f.readlines():

To count up our potential score using the input, we need to convert the content of each line from a string containing two characters, a space, and a newline character into a tuple of two characters. We can call split on the line to extract a list of words from the string. This will discard the whitespace and newline character for us. Then we can rely on Python’s type coercion to convert from string to tuple.

t = tuple(line.split())
total_score += scores[t]

We use the tuple as key to access the scores dictionary and add the value to our total score. total_score then contains our answer to puzzle 1.

Puzzle 2

The second puzzle redefines the right hand column of characters (X, Y, and Z) as the desired outcome of the round. X should result in a loss, Y in a draw, and Z in a win.

This might seem on the surface like a jump in complexity but we can simply adjust the scores in our dictionary to reflect the outcomes.

For any X scenario, the score will be 0 plus the base score for the choice of response - 1 for rock, 2 for paper, and 3 for scissors. For any Y scenario, we add the value of a draw (3), and for any Z scenario (a win), we add 6.

Additionally, for X scenarios, we choose the losing response. For Y scenarios, we choose the same response, and for Z scenarios, we choose the beating response.

scores = {
    ('A', 'X'): 3,
    ('B', 'X'): 1,
    ('C', 'X'): 2,
    ('A', 'Y'): 4,
    ('B', 'Y'): 5,
    ('C', 'Y'): 6,
    ('A', 'Z'): 8,
    ('B', 'Z'): 9,
    ('C', 'Z'): 7,

For ('A', 'X'), we pick scissors to lose against rock and score 3 for the choice of response. For ('B', 'Y'), we pick paper to draw against paper and score 3 for the draw plus 2 for the choice of response.

We run the same loop as in puzzle 1 to produce our new total and get the answer for puzzle 2.

Source code

View the code on GitHub.

Would you like to read something else by me?

« «

» »

« posts | «« home