Intro

The first day was pretty straight forward so let’s get going on Day 2! Today’s puzzle involves elves playing rock, paper, scissors. I’ve been given a strategy guide which tells me how to play each turn to win enough rounds to pass but not so many rounds I look like I’m cheating. I’ve been tasked to calculate the score if I follow the guide exactly.

The puzzle

I’ve been given another plain text input which is the contents of the strategy guide. Each line represents one game of rock, paper, scissors. Every line has Two letters the first is the opponents move and the second is the move I need to make.

Input Means
A Opponent Rock
B Opponent paper
C Opponent Scissors
X I play Rock
Y I play Paper
Z I play Scissors
C X
A Z
C X
C Z
C X
... many many lines of input....

Interpreting that input: C X means that my opponent plays scissors and I play rock and I win. A Z means the opponent plays Rock I play rock to scissors and I lose.

We’re not quite done yet! My score depends on what move I make and the result of the round. To calculate the score for the round I need to add the points I get for the move I played and the points I get for the result of the round. If I win with Rock I get (1 (Rock) + 6 (Win)) points. If I lose with Scissors I get (3 (Scissors) + 0 (Loss)) points.

Move Points Round result Points
Rock 1 Win 6
Paper 2 Draw 3
Scissors 3 Loss 0

Blimey, that is a lot of context! Hahah thankfully the code should be fairly simple.

Input

Okay time for the slurp function to shine again! Lets read the input and use clojure.string/split-lines to get a list of strings representing each round.

(ns day2.core
  (:require [clojure.string :as str]))

(def input (-> (slurp "./advent-of-code/day2/input.txt")
	     str/split-lines))
(take 10 input)
("C X" "C X" "C X" "A Z" "C X" "C Z" "C X" "B Y" "C X" "C X")

Lovely! I have the input all set. Now I can get hacking on a solution!

Part 1

Right, at first I was tempted to try and map each of the different inputs into some representation of the game. However thinking about it, that seems like overkill. There are only 9 permutations of each round so it isn’t too intense to just hard code a map with all possible outcomes. Hopefully I don’t regret this short cut in part 2!

So if I define a map of all inputs to the score for that input I get this:

(def round-input-to-score
      {"A X" 4 ;; 1 + 3 draw
       "A Y" 8 ;; 2 + 6 win
       "A Z" 3 ;; 3 + 0 loss
       "B X" 1 ;; 1 + 0 loss
       "B Y" 5 ;; 2 + 3 draw
       "B Z" 9 ;; 3 + 6 win
       "C X" 7 ;; 1 + 6 win
       "C Y" 2 ;; 2 + 0 loss
       "C Z" 6 ;; 3 + 3 draw
       })

And I can get the score for a particular round like so:

(round-input-to-score "C X")
7

And I’m almost home free! It isn’t the easiest code to understand the problem domain but it gives me a constant time lookup for all the rounds. Quick and dirty is the goal here anyway.

To finish off I’m going to pull the above into a let block, then I can map across the input and sum the results:


(defn part-1 [rock-paper-scissors-rounds]
  (let [round-input-to-score
      {"A X" 4 ;; 1 + 3 draw
       "A Y" 8 ;; 2 + 6 win
       "A Z" 3 ;; 3 + 0 loss
       "B X" 1 ;; 1 + 0 loss
       "B Y" 5 ;; 2 + 3 draw
       "B Z" 9 ;; 3 + 6 win
       "C X" 7 ;; 1 + 6 win
       "C Y" 2 ;; 2 + 0 loss
       "C Z" 6 ;; 3 + 3 draw
       }]
    (reduce + (map round-input-to-score
		 rock-paper-scissors-rounds))))

Finally I just need to call that function with the input:

(part-1 input)
14375

Annnnnnnd… Yeah that’s the right result! Woo! Let’s see move on!

Part 2

Okay part 2! What’s in store… It turns out that our understanding of the strategy guide was wrong. The second letter isn’t the move that I have to make. Instead the second letter represents the outcome I need to achieve. Now I need to calculate the score if I manage to get all the correct outcomes.

Input Means
X Lose
Y Draw
Z Win

The scoring itself hasn’t changed just our previous definition of what each combination of moves scored is now wrong. We need to change it so it returns the score of the move we need to make plus the result of the round. Thankfully that means I just need to juggle my rount-input-to-score map a bit and I’ll be done with part 2!



(defn part-2 [rock-paper-scissors-rounds]
  (let [round-input-to-score
      {"A X" 3 ;; scissors 3 + 0 loss
       "A Y" 4 ;; rock 1 + draw 3
       "A Z" 8 ;; paper 2 + 6 win
       "B X" 1 ;; rock 1 + 0 loss
       "B Y" 5 ;; paper 2 + draw 3
       "B Z" 9 ;; scissors 3 + 6 win
       "C X" 2 ;; paper 2 + 0 loss
       "C Y" 6 ;; scissors 3 + draw 3
       "C Z" 7 ;; rock 1 + 6 win
       }]
    (reduce + (map round-input-to-score
		 rock-paper-scissors-rounds))))
(part-2 input)
10274

And…

Your puzzle answer was 10274.

Both parts of this puzzle are complete!

Yay! That was fun! And pretty easy today! Still, there are 23 days to go! I don’t want to jinx it! Haha

I’ve put the code for this and the other AoC challenges I’ve done on github.

Thanks for reading!