Advent of Code 2022 - Day 2: Rock Paper Scissors
1 2 |
#lang iracket/lang #:require racket (require "../advent.rkt") |
Day 2 - Part 1
Rock, Paper, Scissors
For example, suppose you were given the following strategy guide:
A Y
B X
C Z
We’re told that A=Rock, B=Paper and C=Scissors, and it’s proposed that X=Rock, Y=Paper and Z=Scissors.
We’re also told the score is computed as follows: add the score of the shape (1 for Rock, 2 for Paper and 3 for Scissors) to the outcome (0 if we lost, 3 if a draw and 6 if we won).
What would your total score be if everything goes exactly according to your strategy guide?
1 |
(define in (parse-aoc 2 chars)) |
----------------------------------------------------------------------------------------------------
day02.txt -> 10000 chars, 2500 lines; first 3 lines; last 2 lines:
----------------------------------------------------------------------------------------------------
B Z
C Z
B X
...
C Y
B Z
----------------------------------------------------------------------------------------------------
(parse 2) -> 2500 entries:
----------------------------------------------------------------------------------------------------
((#\B #\Z)
(#\C #\Z)
...
(#\B #\Z))
----------------------------------------------------------------------------------------------------
Parsing gives us a list of pairs of plays e.g. player 1 plays A=Rock, player 2 plays Y=Paper, etc. Let’s define a function that maps a letter to a shape:
1 2 3 4 5 6 7 8 9 10 |
(define (char->shape c) (match c [ #\A 'rock ] [ #\X 'rock ] [ #\B 'paper ] [ #\Y 'paper ] [ #\C 'scissors ] [ #\Z 'scissors ])) (char->shape #\Y) |
’paper
Determine the score of a shape:
1 2 3 4 5 6 7 |
(define (shape-score shape) (match shape [ 'rock 1 ] [ 'paper 2 ] [ 'scissors 3 ])) (shape-score 'scissors) |
3
Determine an outcome:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
(define (outcome us them) (match (cons us them) [ '(rock . scissors) 'win ] [ '(rock . rock) 'draw ] [ '(rock . paper) 'loss ] [ '(paper . rock) 'win ] [ '(paper . paper) 'draw ] [ '(paper . scissors) 'loss ] [ '(scissors . paper) 'win ] [ '(scissors . scissors) 'draw ] [ '(scissors . rock) 'loss ])) (outcome 'paper 'rock) |
’win
Determine the score of an outcome:
1 2 3 4 5 6 7 |
(define (outcome-score outcome) (match outcome [ 'loss 0 ] [ 'draw 3 ] [ 'win 6 ])) (outcome-score 'win) |
6
Let’s create a round
function that accepts a list of characters from the input, e.g. (them us), and computes the score, given the outcome:
1 2 3 4 5 6 7 8 9 |
(define (round pair) (let ([ them (char->shape (first pair)) ] [ us (char->shape (second pair)) ]) (+ (shape-score us) (outcome-score (outcome us them))))) (list (round '(#\A #\Y)) (round '(#\B #\X)) (round '(#\C #\Z))) |
’(8 1 6)
The hard part is done, now all we have to do is fold the +
and round
functions over the list:
1 2 3 |
(foldl (λ (pair sum) (+ (round pair) sum)) ; function to fold 0 ; initial value in) ; list |
12458
Part 2
The Elf finishes helping with the tent and sneaks back over to you. “Anyway, the second column says how the round needs to end: X means you need to lose, Y means you need to end the round in a draw, and Z means you need to win. Good luck!”
Ok, it looks like we’ll need a function to map the second column to an expected outcome:
1 2 3 4 5 6 7 |
(define (expected-outcome c) (match c [ #\X 'loss ] [ #\Y 'draw ] [ #\Z 'win ])) (expected-outcome #\Y) |
’draw
And, we’ll need a function that returns a shape for us to play given the other player’s shape and the expected outcome. Since we already have a function to return an outcome given both players’ choices, we’ll just look through the list of 3 shapes to find the right one:
1 2 3 4 5 6 7 8 9 |
(define (expected-shape pair) (let ([ shapes (map char->shape '(#\A #\B #\C)) ] [ them (char->shape (first pair)) ] [ desired (expected-outcome (second pair)) ]) (findf (λ (shape) (eq? desired (outcome shape them))) shapes))) (expected-shape '(#\A #\Y)) |
’rock
We’ll redefine the round
function with the new information from part 2:
1 2 3 4 5 6 7 8 9 10 |
(define (round pair) (let ([ outcome (expected-outcome (second pair)) ] [ them (char->shape (first pair)) ] [ us (expected-shape pair) ]) (+ (shape-score us) (outcome-score outcome)))) (list (round '(#\A #\Y)) (round '(#\B #\X)) (round '(#\C #\Z))) |
’(4 1 7)
The fold for part 2 is identical, given the new round
:
1 2 3 |
(foldl (λ (pair sum) (+ (round pair) sum)) ; function to fold 0 ; initial value in) ; list |
12683
A much simpler solution
Todd Ginsberg used a much simpler solution, and it was a good reminder for me to look for similar opportunities in the future days!
1 2 3 4 5 6 7 8 9 10 11 12 |
;; Part 1 (for/sum ([ pair in ]) (match pair [ '(#\A #\X) 4 ] [ '(#\A #\Y) 8 ] [ '(#\A #\Z) 3 ] [ '(#\B #\X) 1 ] [ '(#\B #\Y) 5 ] [ '(#\B #\Z) 9 ] [ '(#\C #\X) 7 ] [ '(#\C #\Y) 2 ] [ '(#\C #\Z) 6 ])) |
12458
1 2 3 4 5 6 7 8 9 10 11 12 |
;; Part 2 (for/sum ([ pair in ]) (match pair [ '(#\A #\X) 3 ] [ '(#\A #\Y) 4 ] [ '(#\A #\Z) 8 ] [ '(#\B #\X) 1 ] [ '(#\B #\Y) 5 ] [ '(#\B #\Z) 9 ] [ '(#\C #\X) 2 ] [ '(#\C #\Y) 6 ] [ '(#\C #\Z) 7 ])) |
12683