AoC_2022/src/day02.rs

126 lines
3.2 KiB
Rust

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<Outcome> 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<Self, Self::Err> {
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::<Vec<Choice>>();
(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()
}