use std::str::FromStr; use aoc_runner_derive::{aoc, aoc_generator}; #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Choice { Rock, Paper, Scissors, } #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Outcome { Win, Loose, Draw, } impl Outcome { fn other(&self, choice: &Choice) -> Choice { match (self, choice) { (Outcome::Win, Choice::Rock) => Choice::Paper, (Outcome::Win, Choice::Paper) => Choice::Scissors, (Outcome::Win, Choice::Scissors) => Choice::Rock, (Outcome::Loose, Choice::Rock) => Choice::Scissors, (Outcome::Loose, Choice::Paper) => Choice::Rock, (Outcome::Loose, Choice::Scissors) => Choice::Paper, (Outcome::Draw, other) => *other, } } } impl From for usize { fn from(val: Outcome) -> Self { match val { Outcome::Win => 6, Outcome::Loose => 0, Outcome::Draw => 3, } } } impl From<&Choice> for Outcome { fn from(value: &Choice) -> Self { match value { Choice::Rock => Outcome::Loose, Choice::Paper => Outcome::Draw, Choice::Scissors => Outcome::Win, } } } impl Choice { fn shape_score(&self) -> usize { match self { Choice::Rock => 1, Choice::Paper => 2, Choice::Scissors => 3, } } fn outcome(&self, other: &Self) -> Outcome { match (self, other) { (Choice::Rock, Choice::Scissors) => Outcome::Win, (Choice::Paper, Choice::Rock) => Outcome::Win, (Choice::Scissors, Choice::Paper) => Outcome::Win, (Choice::Rock, Choice::Paper) => Outcome::Loose, (Choice::Paper, Choice::Scissors) => Outcome::Loose, (Choice::Scissors, Choice::Rock) => Outcome::Loose, _ => Outcome::Draw, } } } impl FromStr for Choice { type Err = (); fn from_str(s: &str) -> Result { match s.to_ascii_uppercase().as_str() { "A" | "X" => Ok(Self::Rock), "B" | "Y" => Ok(Self::Paper), "C" | "Z" => Ok(Self::Scissors), _ => unreachable!(), } } } #[aoc_generator(day2)] pub fn input_generator(input: &str) -> Vec<(Choice, Choice)> { input .lines() .map(|line| { let rule = line .split_ascii_whitespace() .map(|r| r.parse().unwrap()) .collect::>(); (rule[0], rule[1]) }) .collect() } #[aoc(day2, part1)] pub fn solve_part1(input: &[(Choice, Choice)]) -> usize { input .iter() .map(|(other, mine)| { let shape_score = mine.shape_score(); let outcome: usize = mine.outcome(other).into(); shape_score + outcome }) .sum() } #[aoc(day2, part2)] pub fn solve_part2(input: &[(Choice, Choice)]) -> usize { input .iter() .map(|(other, goal)| { let goal: Outcome = goal.into(); let mine = goal.other(other); let shape_score = mine.shape_score(); let outcome: usize = goal.into(); shape_score + outcome }) .sum() }