# AoC 2022 Day 2: Roshamboinator

## Part 1

Given a list of Rock Paper Scissors matches with A,B,C or X,Y,Z corresponding to those plays and scoring 1,2,3 points for your play plus 0,3,6 for a loss, draw, or win, what is your total score.

Cool. Let’s over engineer it!

First, a Play and an Outcome:

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum Play {
Rock,
Paper,
Scissors,
}

#[derive(Copy, Clone, Debug)]
enum Outcome {
Lose,
Draw,
Win,
}

Now, for Play, we want to be able to build them from the input values, get the value of any play, or determine the Outcome for a match:

impl Play {
fn new(c: char) -> Play {
use Play::*;

match c {
'A' | 'X' => Rock,
'B' | 'Y' => Paper,
'C' | 'Z' => Scissors,
_ => panic!("unknown play: {:?}", c),
}
}

fn value(self) -> i32 {
use Play::*;

match self {
Rock => 1,
Paper => 2,
Scissors => 3,
}
}

fn vs(self, other: Play) -> Outcome {
use Outcome::*;
use Play::*;

match (self, other) {
(a, b) if a == b => Draw,

(Rock, Scissors) | (Scissors, Paper) | (Paper, Rock) => Win,

_ => Lose,
}
}
}

The vs function is my favorite. I previously hadn’t gotten to use multiple cases in a match (with |) or guards (with if). Pretty powerful syntax there. I do love languages with solid pattern matching.

Next, we need the value for Outcome as well:

impl Outcome {
fn value(self) -> i32 {
use Outcome::*;

match self {
Lose => 0,
Draw => 3,
Win => 6,
}
}
}

And then we should be able to parse the input and calculate a score:

fn part1(filename: &Path) -> String {
let mut total_score = 0;

let them = Play::new(line.chars().nth(0).expect("must have 1 char per line"));
let us = Play::new(line.chars().nth(2).expect("must have 3 chars per line"));

total_score += us.value() + us.vs(them).value();
}

total_score.to_string()
}

It’s not a bit weird to use nth to pull out the chars, but I was having some issues with String vs &str comparisons. Chars just work.

Run it on my input:

13509
took 662.916µs

Double cool.