diff --git a/src/bin/day02.rs b/src/bin/day02.rs index 153648a..831a32a 100644 --- a/src/bin/day02.rs +++ b/src/bin/day02.rs @@ -1,7 +1,9 @@ +use std::str::FromStr; + use aoc_2022::*; use color_eyre::eyre::Result; -use itertools::Itertools; +use thiserror::Error; use tracing::*; use tracing_subscriber::EnvFilter; @@ -22,6 +24,32 @@ impl Shape { } } +#[derive(Error, Debug)] +enum ShapeError { + #[error("empty string given")] + Empty, + + #[error("unknown shape ‹{0}›")] + UnknownShape(String), +} + +impl FromStr for Shape { + type Err = ShapeError; + + fn from_str(s: &str) -> Result { + if s.is_empty() { + return Err(ShapeError::Empty); + } + + match s { + "A" | "X" => Ok(Shape::Rock), + "B" | "Y" => Ok(Shape::Paper), + "C" | "Z" => Ok(Shape::Scissors), + _ => Err(ShapeError::UnknownShape(s.to_string())), + } + } +} + #[derive(Debug, Clone, Copy)] enum Outcome { Lose, @@ -35,6 +63,28 @@ struct Round { me: Shape, } +#[derive(Error, Debug)] +enum RoundError { + #[error("invalid shape ‹{0}›")] + InvalidShape(#[from] ShapeError), +} + +impl FromStr for Round { + type Err = RoundError; + + fn from_str(s: &str) -> Result { + let mut split_str = s.split(' '); + + let opponent = split_str.next().unwrap().parse::(); + let me = split_str.next().unwrap().parse::(); + + Ok(Round { + opponent: opponent?, + me: me?, + }) + } +} + impl Round { fn score(&self) -> i32 { let shape_score = self.me.score(); @@ -93,30 +143,7 @@ fn part_2(input: &Input) -> Output { } fn parse_input(pathname: &str) -> Input { - file_to_lines(pathname) - .iter() - .map(|s| { - let mut split_str = s.split(" "); - - let opponent = split_str.next().unwrap(); - let me = split_str.next().unwrap(); - - Round { - opponent: match opponent { - "A" => Shape::Rock, - "B" => Shape::Paper, - "C" => Shape::Scissors, - _ => panic!("invalid choice"), - }, - me: match me { - "X" => Shape::Rock, - "Y" => Shape::Paper, - "Z" => Shape::Scissors, - _ => panic!("invalid choice"), - }, - } - }) - .collect() + file_to_structs(pathname) } fn main() -> Result<()> {