diff --git a/bin/src/main.rs b/bin/src/main.rs index 574e152..a197ac3 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -77,11 +77,11 @@ fn day5(input: String) { } fn day6(input: String) { - let races = Races::from_multiple_races(&input).expect("Failed to parse races"); + let races = Races::from_str(&input).expect("Failed to parse races"); let winning_product = races.get_winning_product(); println!("Winning product for multiple races: {winning_product}"); - let race = Races::from_single_race(&input).expect("Failed to parse race"); + let race = races.as_single_race().expect("Failed to parse race"); let winning_product = race.get_winning_product(); println!("Winning product for single race: {winning_product}"); } diff --git a/lib/boat_race/src/lib.rs b/lib/boat_race/src/lib.rs index 7f88417..c90068b 100644 --- a/lib/boat_race/src/lib.rs +++ b/lib/boat_race/src/lib.rs @@ -1,4 +1,4 @@ -use std::num::ParseIntError; +use std::{num::ParseIntError, str::FromStr}; #[derive(Debug)] pub enum ParseRaceError { @@ -6,6 +6,12 @@ pub enum ParseRaceError { Invalid(String), } +impl From for ParseRaceError { + fn from(value: ParseIntError) -> Self { + Self::ParseInt(value) + } +} + pub struct Race { time: u64, distance: u64, @@ -65,32 +71,11 @@ pub struct Races { races: Vec, } -impl Races { - pub fn get_winning_product(&self) -> u64 { - self.races.iter().map(Race::find_winning_conditions_amount).product() - } +impl FromStr for Races { + type Err = ParseRaceError; - pub fn from_single_race(races: &str) -> Result { - let numbers = races - .lines() - .map(|line| { - line.split(':') - .last() - .ok_or_else(|| ParseRaceError::Invalid("Failed to get numbers".to_string()))? - .split_ascii_whitespace() - .collect::() - .parse::() - .map_err(ParseRaceError::ParseInt) - }) - .collect::, ParseRaceError>>()?; - - let races = vec![Race::new(numbers[0], numbers[1])]; - - Ok(Self { races }) - } - - pub fn from_multiple_races(races: &str) -> Result { - let numbers = races + fn from_str(s: &str) -> Result { + let numbers = s .lines() .map(|line| { line.split(':') @@ -98,9 +83,9 @@ impl Races { .ok_or_else(|| ParseRaceError::Invalid("Failed to get numbers".to_string()))? .split_ascii_whitespace() .map(|n| n.parse::().map_err(ParseRaceError::ParseInt)) - .collect::, ParseRaceError>>() + .collect::, _>>() }) - .collect::>, ParseRaceError>>()?; + .collect::>, _>>()?; let races = numbers[0] .iter() @@ -112,6 +97,25 @@ impl Races { } } +impl Races { + pub fn get_winning_product(&self) -> u64 { + self.races.iter().map(Race::find_winning_conditions_amount).product() + } + + pub fn as_single_race(self) -> Result { + let (time, distance) = self + .races + .into_iter() + .fold((String::new(), String::new()), |(time, distance), race| { + (time + &race.time.to_string(), distance + &race.distance.to_string()) + }); + + let race = Race::new(time.parse()?, distance.parse()?); + + Ok(Self { races: vec![race] }) + } +} + #[cfg(test)] mod tests { use super::*; @@ -121,7 +125,7 @@ Distance: 9 40 200"; #[test] fn solution_1() { - let product = Races::from_multiple_races(EXAMPLE) + let product = Races::from_str(EXAMPLE) .expect("Failed to parse races") .get_winning_product(); assert_eq!(product, 288) @@ -129,7 +133,7 @@ Distance: 9 40 200"; #[test] fn solution_2() { - let product = Races::from_single_race(EXAMPLE) + let product = Races::from_str(EXAMPLE) .expect("Failed to parse race") .get_winning_product(); assert_eq!(product, 71503);