diff --git a/rs/src/y2022/d02.rs b/rs/src/y2022/d02.rs index e08068a..f563b1c 100644 --- a/rs/src/y2022/d02.rs +++ b/rs/src/y2022/d02.rs @@ -6,22 +6,54 @@ enum Choice { } impl Choice { - fn score_against(self, other: Self) -> u32 { - use self::Choice::*; + fn score(self) -> u32 { + match self { + Self::Rock => 1, + Self::Paper => 2, + Self::Scissors => 3, + } + } - (match self { - Rock => 1, - Paper => 2, - Scissors => 3, - } + match (self, other) { - (Rock, Paper) | (Paper, Scissors) | (Scissors, Rock) => 0, - (Rock, Rock) | (Paper, Paper) | (Scissors, Scissors) => 3, - (Rock, Scissors) | (Paper, Rock) | (Scissors, Paper) => 6, - }) + fn against(self, opponent: Self) -> Outcome { + use self::Choice::*; + match (self, opponent) { + (Rock, Paper) | (Paper, Scissors) | (Scissors, Rock) => Outcome::Lose, + (Rock, Rock) | (Paper, Paper) | (Scissors, Scissors) => Outcome::Draw, + (Rock, Scissors) | (Paper, Rock) | (Scissors, Paper) => Outcome::Win, + } } } -fn read_round(line: &str) -> (Choice, Choice) { +#[derive(Clone, Copy, PartialEq, Eq)] +enum Outcome { + Lose, + Draw, + Win, +} + +impl Outcome { + fn score(self) -> u32 { + match self { + Outcome::Lose => 0, + Outcome::Draw => 3, + Outcome::Win => 6, + } + } + + fn against(self, opponent: Choice) -> Choice { + match (self, opponent) { + (Self::Lose, Choice::Rock) => Choice::Scissors, + (Self::Lose, Choice::Paper) => Choice::Rock, + (Self::Lose, Choice::Scissors) => Choice::Paper, + (Self::Draw, c) => c, + (Self::Win, Choice::Rock) => Choice::Paper, + (Self::Win, Choice::Paper) => Choice::Scissors, + (Self::Win, Choice::Scissors) => Choice::Rock, + } + } +} + +fn read_round(line: &str) -> (Choice, Choice, Outcome) { let elems = line.split(' ').take(2).collect::>(); let l = match elems[0] { "A" => Choice::Rock, @@ -29,27 +61,34 @@ fn read_round(line: &str) -> (Choice, Choice) { "C" => Choice::Scissors, _ => panic!(), }; - let r = match elems[1] { - "X" => Choice::Rock, - "Y" => Choice::Paper, - "Z" => Choice::Scissors, + let (rc, ro) = match elems[1] { + "X" => (Choice::Rock, Outcome::Lose), + "Y" => (Choice::Paper, Outcome::Draw), + "Z" => (Choice::Scissors, Outcome::Win), _ => panic!(), }; - (l, r) + (l, rc, ro) } pub fn solve(input: String) -> anyhow::Result<()> { - let choices = input + let matches = input .lines() .map(|l| read_round(l.trim())) .collect::>(); // Part 1 - let score = choices + let score = matches .iter() - .map(|(l, r)| r.score_against(*l)) + .map(|(l, r, _)| r.score() + r.against(*l).score()) .sum::(); println!("Part 1: {score}"); + // Part 2 + let score = matches + .iter() + .map(|(l, _, r)| r.against(*l).score() + r.score()) + .sum::(); + println!("Part 2: {score}"); + Ok(()) }