diff --git a/2023/day6/src/main.rs b/2023/day6/src/main.rs index 5cac14f..470d5cc 100644 --- a/2023/day6/src/main.rs +++ b/2023/day6/src/main.rs @@ -1,6 +1,6 @@ const FILE_STR: &str = include_str!("input.txt"); -#[derive(Debug, Default)] +#[derive(Debug, Default, Copy, Clone)] struct RaceRecord { time: usize, distance: usize, @@ -13,14 +13,111 @@ struct Races { impl Races { fn parse(records: &str) -> Self { - todo!(); + let mut lines = records + .split('\n') + .map(|s| s.trim()) + .filter(|s| !s.is_empty()) + .map(|s| s.split(':')); + let times: Vec<_> = lines + .next() + .unwrap() + .nth(1) + .unwrap() + .split_whitespace() + .map(|n| n.trim()) + .filter(|n| !n.is_empty()) + .map(|n| n.parse::().unwrap()) + .collect(); + + let distances: Vec<_> = lines + .next() + .unwrap() + .nth(1) + .unwrap() + .split_whitespace() + .map(|n| n.trim()) + .filter(|n| !n.is_empty()) + .map(|n| n.parse::().unwrap()) + .collect(); + + let mut r = Races::default(); + assert_eq!(times.len(), distances.len()); + for i in 0..times.len() { + r.records.push(RaceRecord { + time: times[i], + distance: distances[i], + }) + } + + r + } + + fn parse_single(records: &str) -> Self { + let mut lines = records + .split('\n') + .map(|s| s.trim()) + .filter(|s| !s.is_empty()) + .map(|s| s.split(':')); + + let time = lines + .next() + .unwrap() + .nth(1) + .unwrap() + .replace(' ', "") + .parse::().unwrap(); + + let distance = lines + .next() + .unwrap() + .nth(1) + .unwrap() + .replace(' ', "") + .parse::().unwrap(); + + Races { + records: Vec::from([RaceRecord { time, distance}]) + } + } + + fn calculate_winning_counts(&self) -> Vec { + self.records + .iter() + .map(|r| winning_possibilities(*r).len()) + .collect() + } + + fn calculate_possible_win_product(&self) -> usize { + self.calculate_winning_counts() + .into_iter() + .reduce(|prev, curr| prev * curr) + .unwrap() } } -fn part_one() {} +fn winning_possibilities(race: RaceRecord) -> Vec { + let distance_calculation = + |race_length: usize, button_time: usize| button_time * (race_length - button_time); + let possible_range = 1..race.time; + possible_range + .filter_map(|button_time| { + let res = distance_calculation(race.time, button_time); + if res > race.distance { + Some(res) + } else { + None + } + }) + .collect() +} + +fn part_one() { + let records = Races::parse(FILE_STR); + println!("Part 1 Product of winning possibilitiesL {}", records.calculate_possible_win_product()); +} fn main() { - part_one(); + part_one(); } #[cfg(test)] @@ -28,4 +125,16 @@ mod tests { const EXAMPLE_FILE_STR: &'static str = include_str!("example-input.txt"); use super::*; -} \ No newline at end of file + + #[test] + fn test_calculate_winning_counts() { + let races = Races::parse(EXAMPLE_FILE_STR); + assert_eq!(Vec::from([4, 8, 9]), races.calculate_winning_counts()); + } + + #[test] + fn test_calculate_possible_win_product() { + let races = Races::parse(EXAMPLE_FILE_STR); + assert_eq!(288, races.calculate_possible_win_product()); + } +}