diff --git a/advent_of_code/2023/6/Cargo.toml b/advent_of_code/2023/6/Cargo.toml new file mode 100644 index 0000000..c3650cd --- /dev/null +++ b/advent_of_code/2023/6/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "main" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +nom = "7.1.3" diff --git a/advent_of_code/2023/6/input.txt b/advent_of_code/2023/6/input.txt new file mode 100644 index 0000000..cfc0d59 --- /dev/null +++ b/advent_of_code/2023/6/input.txt @@ -0,0 +1,2 @@ +Time: 35 93 73 66 +Distance: 212 2060 1201 1044 \ No newline at end of file diff --git a/advent_of_code/2023/6/src/main.rs b/advent_of_code/2023/6/src/main.rs new file mode 100644 index 0000000..3b86bd0 --- /dev/null +++ b/advent_of_code/2023/6/src/main.rs @@ -0,0 +1,100 @@ +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); + } +} diff --git a/advent_of_code/2023/6/test_input.txt b/advent_of_code/2023/6/test_input.txt new file mode 100644 index 0000000..b39f49d --- /dev/null +++ b/advent_of_code/2023/6/test_input.txt @@ -0,0 +1,2 @@ +Time: 7 15 30 +Distance: 9 40 200 \ No newline at end of file