diff --git a/src/bin/day2.rs b/src/bin/day2.rs new file mode 100644 index 0000000..d279934 --- /dev/null +++ b/src/bin/day2.rs @@ -0,0 +1,105 @@ +use aoc2022::StdError; +use std::fs::File; +use std::io::{BufRead, BufReader}; + +#[derive(PartialEq, Clone, Copy)] +enum Move { + Rock, + Paper, + Scissors, +} + +enum Outcome { + Win, + Loss, + Draw, +} + +impl Outcome { + fn from_char(c: char) -> Option { + match c { + 'X' => Some(Self::Loss), + 'Y' => Some(Self::Draw), + 'Z' => Some(Self::Win), + _ => None, + } + } + + fn score(&self) -> u8 { + match self { + Self::Win => 6, + Self::Draw => 3, + Self::Loss => 0, + } + } +} + +impl Move { + fn from_char(c: char) -> Option { + match c { + 'A' | 'X' => Some(Self::Rock), + 'B' | 'Y' => Some(Self::Paper), + 'C' | 'Z' => Some(Self::Scissors), + _ => None, + } + } + + fn outcome_for_move(&self, other: &Self) -> Outcome { + match (self, other) { + (Self::Rock, Self::Rock) + | (Self::Paper, Self::Paper) + | (Self::Scissors, Self::Scissors) => Outcome::Draw, + (Self::Rock, Self::Scissors) => Outcome::Win, + (Self::Rock, Self::Paper) => Outcome::Loss, + (Self::Paper, Self::Rock) => Outcome::Win, + (Self::Paper, Self::Scissors) => Outcome::Loss, + (Self::Scissors, Self::Paper) => Outcome::Win, + (Self::Scissors, Self::Rock) => Outcome::Loss, + } + } + + fn move_for_outcome(&self, outcome: Outcome) -> Move { + match (self, outcome) { + (Self::Rock, Outcome::Win) => Move::Paper, + (Self::Rock, Outcome::Loss) => Move::Scissors, + (Self::Paper, Outcome::Win) => Move::Scissors, + (Self::Paper, Outcome::Loss) => Move::Rock, + (Self::Scissors, Outcome::Win) => Move::Rock, + (Self::Scissors, Outcome::Loss) => Move::Paper, + (_, Outcome::Draw) => *self, + } + } + + fn score(&self) -> u8 { + match self { + Self::Rock => 1, + Self::Paper => 2, + Self::Scissors => 3, + } + } +} + +fn main() -> StdError<()> { + let lines: Vec<_> = BufReader::new(File::open("input/day2.txt")?) + .lines() + .filter_map(Result::ok) + .map(|l| { + let spl: Vec<_> = l.chars().collect(); + assert!(spl.len() == 3); + (spl[0], spl[2]) + }) + .collect(); + let part1: u32 = lines + .iter() + .map(|(a, b)| (Move::from_char(*a).unwrap(), Move::from_char(*b).unwrap())) + .map(|(opponent, you)| (you.score() + you.outcome_for_move(&opponent).score()) as u32) + .sum(); + println!("Part 1: {}", part1); + let part2: u32 = lines + .iter() + .map(|(a, b)| (Move::from_char(*a).unwrap(), Outcome::from_char(*b).unwrap())) + .map(|(opp, out)| (out.score() + opp.move_for_outcome(out).score()) as u32) + .sum(); + println!("Part 2: {}", part2); + Ok(()) +}