use aoc_runner_derive::{aoc, aoc_generator}; struct Race { time: u64, distance: u64, } impl Race { fn winning_times(&self) -> Vec { let mut result: Vec = vec![]; for t in 0..=self.time { if t * (self.time - t) > self.distance { result.push(t); } } result } } #[aoc_generator(day6)] fn parse(input: &str) -> Vec { let mut lines = input.lines(); let times: Vec = lines.next().unwrap().split(": ").collect::>()[1] .trim_start() .split(" ") .filter_map(|t| t.parse::().ok()) .collect(); let distances: Vec = lines.next().unwrap().split(": ").collect::>()[1] .trim_start() .split(" ") .filter_map(|t| t.parse::().ok()) .collect(); assert_eq!(times.len(), distances.len()); (0..times.len()) .map(|i| Race { time: times[i], distance: distances[i], }) .collect() } #[aoc(day6, part1)] fn part1(input: &[Race]) -> u64 { input .iter() .map(|race| race.winning_times().len() as u64) .collect::>() .iter() .product() } #[aoc(day6, part2)] fn part2(input: &[Race]) -> u64 { let time = input .iter() .map(|race| race.time) .collect::>() .iter() .map(|t| t.to_string()) .collect::>() .join("") .parse::() .unwrap(); let distance = input .iter() .map(|race| race.distance) .collect::>() .iter() .map(|t| t.to_string()) .collect::>() .join("") .parse::() .unwrap(); let race = Race { time, distance }; race.winning_times().len() as u64 } #[cfg(test)] mod tests { use super::*; const SAMPLE_DATA: &'static str = r#"Time: 7 15 30 Distance: 9 40 200 "#; #[test] fn sample_data() { let races = parse(&SAMPLE_DATA); assert_eq!(part1(&races), 288); assert_eq!(part2(&races), 71503); } }