use std::iter::zip; use nom::{ bytes::complete::tag, character::complete::{multispace0, multispace1, u64}, multi::separated_list1, sequence::tuple, IResult, }; fn parse_input(input: &str) -> IResult<&str, Vec<(u64, u64)>> { let (input, result) = tuple(( tag("Time:"), multispace0, separated_list1(multispace1, u64), multispace0, tag("Distance:"), multispace0, separated_list1(multispace1, u64), ))(input) .map(|(i, (_, _, times, _, _, _, distances))| (i, (times, distances)))?; let result = zip(result.0, result.1).collect(); Ok((input, result)) } fn record_beating_ways(time_distance_pair: (u64, u64)) -> usize { (1..=time_distance_pair.0) .into_iter() .filter(|&time_charging| { (time_distance_pair.0 - time_charging) * time_charging > time_distance_pair.1 }) .count() } fn solve_1(time_distance_pairs: &[(u64, u64)]) -> u64 { time_distance_pairs .iter() .map(|&pair| record_beating_ways(pair) as u64) .product() } fn solve_2(time_distance_pairs: &[(u64, u64)]) -> u64 { let time_distance_pair = time_distance_pairs.iter().fold( (0, 0), |(output_time, output_distance), &(time, distance)| { let time_len = (time as f64).log10().floor() as u32 + 1; let distance_len = (distance as f64).log10().floor() as u32 + 1; ( output_time * 10u64.pow(time_len) as u64 + time, output_distance * 10u64.pow(distance_len) as u64 + distance, ) }, ); record_beating_ways(time_distance_pair) as u64 } fn main() { println!("Hello, this is Patrick!"); let input_text = include_str!("../input.txt"); let (_, time_distance_pairs) = parse_input(input_text).unwrap(); println!( "The product of the number of ways you could beat the record is {}", solve_1(&time_distance_pairs[..]) ); println!( "The longer race can be won in {} ways", solve_2(&time_distance_pairs[..]) ); } #[cfg(test)] mod tests { use super::*; #[test] fn test_1() { let input_text = include_str!("../test_input.txt"); let (_, time_distance_pairs) = parse_input(input_text).unwrap(); assert_eq!(solve_1(&time_distance_pairs[..]), 288); } #[test] fn test_2() { let input_text = include_str!("../test_input.txt"); let (_, time_distance_pairs) = parse_input(input_text).unwrap(); assert_eq!(solve_2(&time_distance_pairs[..]), 71503); } }