use std::ops::Add;
use aoc::{answer, parser};
use parse_display::FromStr;
#[derive(FromStr, PartialEq, Debug, Copy, Clone)]
enum Move {
#[from_str(regex = "A|X")]
Rock,
#[from_str(regex = "B|Y")]
Paper,
#[from_str(regex = "C|Z")]
Scissor,
}
impl Add for Move {
type Output = usize;
fn add(self, rhs: Self) -> Self::Output {
let score = self as usize + 1;
let outcome = match (self, rhs) {
(Move::Rock, Move::Rock)
| (Move::Paper, Move::Paper)
| (Move::Scissor, Move::Scissor) => 3,
(Move::Rock, Move::Scissor)
| (Move::Paper, Move::Rock)
| (Move::Scissor, Move::Paper) => 6,
(Move::Paper, Move::Scissor)
| (Move::Scissor, Move::Rock)
| (Move::Rock, Move::Paper) => 0,
};
outcome + score
}
}
#[derive(FromStr, PartialEq, Debug, Clone, Copy)]
#[display("{prediction} {strategy}")]
struct Match {
prediction: Move,
strategy: Move,
}
impl Match {
pub fn score(self) -> usize {
self.strategy + self.prediction
}
}
fn main() {
let score = parser::lines::<Match>().map(Match::score).sum::<usize>();
answer!(
"If everything goes exactly according to strategy the final score should be {}",
score
);
}