diff --git a/day-06/Cargo.toml b/day-06/Cargo.toml new file mode 100644 index 0000000..7b5b081 --- /dev/null +++ b/day-06/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "day-06" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +itertools = "0.12.0" +nom = "7.1.3" +nom-supreme = "0.8.0" +tracing = "0.1.40" +tracing-subscriber = "0.3.18" + +[dev-dependencies] +env_logger = "0.10.1" +test-log = "0.2.13" diff --git a/day-06/input.txt b/day-06/input.txt new file mode 100644 index 0000000..83c7740 --- /dev/null +++ b/day-06/input.txt @@ -0,0 +1,2 @@ +Time: 35 69 68 87 +Distance: 213 1168 1086 1248 \ No newline at end of file diff --git a/day-06/src/main.rs b/day-06/src/main.rs new file mode 100644 index 0000000..ac6d959 --- /dev/null +++ b/day-06/src/main.rs @@ -0,0 +1,73 @@ +use nom::{ + bytes::complete::is_not, + character::complete::{self, line_ending, space1}, + multi::separated_list1, + sequence::separated_pair, + IResult, Parser as _, +}; +use nom_supreme::ParserExt as _; +use tracing::instrument; + +#[derive(Debug, Clone, Eq, PartialEq)] +struct Race { + time: u64, + record: u64, +} + +impl Race { + fn distance(&self) -> Vec { + (0..self.time) + .map(|t| t * (self.time - t)) + .collect::>() + } +} + +fn nums(input: &str) -> IResult<&str, Vec> { + is_not("0123456789") + .precedes(separated_list1(space1, complete::u64)) + .parse(input) +} + +fn parse_times(input: &str) -> IResult<&str, Vec> { + let (input, (times, records)) = separated_pair(nums, line_ending, nums).parse(input)?; + + let races = itertools::izip!(×, &records) + .map(|(&time, &record)| Race { time, record }) + .collect(); + + Ok((input, races)) +} + +#[instrument] +fn part_1(input: &str) -> usize { + let (_, races) = parse_times(input).unwrap(); + + let results = races + .iter() + .map(|r| { + r.distance() + .into_iter() + .filter(|&d| d > r.record) + .collect::>() + }) + .collect::>>(); + + results.iter().map(Vec::len).product() +} + +fn main() { + let input = include_str!("../input.txt"); + println!("Part 1: {}", part_1(input)); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test_log::test] + fn test_part_1() { + tracing::info!("Hello world"); + let input = include_str!("../test-input.txt"); + assert_eq!(part_1(input), 288); + } +} diff --git a/day-06/test-input.txt b/day-06/test-input.txt new file mode 100644 index 0000000..b39f49d --- /dev/null +++ b/day-06/test-input.txt @@ -0,0 +1,2 @@ +Time: 7 15 30 +Distance: 9 40 200 \ No newline at end of file