From ceb7edff900e3bdfaa11adaf3ae8f6aa90b97b18 Mon Sep 17 00:00:00 2001 From: Jan-Bulthuis Date: Tue, 3 Dec 2024 16:45:33 +0100 Subject: [PATCH] Day3 --- .gitignore | 2 + Cargo.lock | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 10 +++ src/day1.rs | 54 +++++++++++++++ src/day2.rs | 86 +++++++++++++++++++++++ src/day3.rs | 66 ++++++++++++++++++ src/day4.rs | 31 +++++++++ src/lib.rs | 11 +++ 8 files changed, 452 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/day1.rs create mode 100644 src/day2.rs create mode 100644 src/day3.rs create mode 100644 src/day4.rs create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a478d5f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target/ +input/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c7776f6 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,192 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "aoc-runner" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d21ef9204ad206a5a3e918e9920da04e1118ad91ce4f23570be964b9d6b9dfcb" + +[[package]] +name = "aoc-runner-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba8b944269d3fee645d281b1335e1797044db497bb02d0098cc3fdb8900069cc" +dependencies = [ + "aoc-runner-internal", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "aoc-runner-internal" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "274b0ba7f3669a45ec0aaacf94eb032a749de880ab776091576cca94037c9982" +dependencies = [ + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "aoc_2024" +version = "0.1.0" +dependencies = [ + "aoc-runner", + "aoc-runner-derive", + "nom", + "regex", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..18f5e65 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "aoc_2024" +version = "0.1.0" +edition = "2021" + +[dependencies] +aoc-runner = "0.3.0" +aoc-runner-derive = "0.3.0" +nom = "7.1.3" +regex = "1.11.1" diff --git a/src/day1.rs b/src/day1.rs new file mode 100644 index 0000000..3788021 --- /dev/null +++ b/src/day1.rs @@ -0,0 +1,54 @@ +use aoc_runner_derive::{aoc, aoc_generator}; +use nom::character::complete::multispace0; +use nom::multi::many1; +use nom::{character::complete::u64 as parse_u64, IResult}; + +#[aoc_generator(day1)] +pub fn generator(input: &str) -> Vec<(u64, u64)> { + many1(parse_line)(input).unwrap().1 +} + +fn parse_line(input: &str) -> IResult<&str, (u64, u64)> { + let (input, left) = parse_u64(input)?; + let (input, _) = multispace0(input)?; + let (input, right) = parse_u64(input)?; + let (input, _) = multispace0(input)?; + Ok((input, (left, right))) +} + +#[aoc(day1, part1)] +pub fn part1(input: &[(u64, u64)]) -> u64 { + let (mut left, mut right): (Vec, Vec) = input.iter().copied().unzip(); + left.sort(); + right.sort(); + left.iter() + .zip(right.iter()) + .map(|(l, r)| (*l).abs_diff(*r)) + .sum() +} + +#[aoc(day1, part2)] +pub fn part2(input: &[(u64, u64)]) -> usize { + let (mut left, mut right): (Vec, Vec) = input.iter().copied().unzip(); + left.sort(); + right.sort(); + + let mut l; + let mut r = 0; + let mut score = 0usize; + for value in left { + l = r; + while l < right.len() && right[l] < value { + l += 1 + } + r = l; + while r < right.len() && right[r] <= value { + r += 1 + } + score += (value as usize) * (r - l); + if r == right.len() - 1 { + break; + }; + } + score +} diff --git a/src/day2.rs b/src/day2.rs new file mode 100644 index 0000000..3684149 --- /dev/null +++ b/src/day2.rs @@ -0,0 +1,86 @@ +use aoc_runner_derive::{aoc, aoc_generator}; +use nom::character::complete::{newline, space0}; +use nom::multi::{many0, many1}; +use nom::{character::complete::i64 as parse_usize, IResult}; + +#[aoc_generator(day2)] +pub fn generator(input: &str) -> Vec> { + many1(parse_line)(input).unwrap().1 +} + +fn parse_level(input: &str) -> IResult<&str, isize> { + let (input, res) = parse_usize(input)?; + let (input, _) = space0(input)?; + Ok((input, res as isize)) +} + +fn parse_line(input: &str) -> IResult<&str, Vec> { + let (input, levels) = many1(parse_level)(input)?; + let (input, _) = many0(newline)(input)?; + Ok((input, levels)) +} + +#[aoc(day2, part1)] +pub fn part1(input: &[Vec]) -> usize { + input.iter().filter(|vec| is_valid(vec)).count() +} + +fn is_valid(input: &[isize]) -> bool { + let mut direction = 0; + for i in 0..(input.len() - 1) { + let diff = input[i + 1] - input[i]; + if diff == 0 { + return false; + } else if (1..=3).contains(&diff) { + if direction == -1 { + return false; + } + direction = 1; + } else if (1..=3).contains(&-diff) { + if direction == 1 { + return false; + } + direction = -1; + } else { + return false; + } + } + true +} + +#[aoc(day2, part2)] +pub fn part2(input: &[Vec]) -> usize { + input + .iter() + .filter(|rec| (0..rec.len()).any(|i| is_valid2(rec, i))) + .count() +} + +fn is_valid2(input: &[isize], skip: usize) -> bool { + let mut direction = 0; + for i in 0..(input.len() - 2) { + let diff = if skip <= i { + input[i + 2] - input[i + 1] + } else if skip == i + 1 { + input[i + 2] - input[i] + } else { + input[i + 1] - input[i] + }; + if diff == 0 { + return false; + } else if (1..=3).contains(&diff) { + if direction == -1 { + return false; + } + direction = 1; + } else if (1..=3).contains(&-diff) { + if direction == 1 { + return false; + } + direction = -1; + } else { + return false; + } + } + true +} diff --git a/src/day3.rs b/src/day3.rs new file mode 100644 index 0000000..6496cc5 --- /dev/null +++ b/src/day3.rs @@ -0,0 +1,66 @@ +use aoc_runner_derive::{aoc, aoc_generator}; +use regex::Regex; +#[aoc_generator(day3)] +fn parse(input: &str) -> String { + input.to_string() +} + +#[aoc(day3, part1)] +fn part1(input: &str) -> i64 { + Regex::new(r"mul\((?[0-9]{1,3}),(?[0-9]{1,3})\)") + .unwrap() + .captures_iter(input) + .fold(0, |a, c| { + a + c.get(1).unwrap().as_str().parse::().unwrap() + * c.get(2).unwrap().as_str().parse::().unwrap() + }) +} + +#[aoc(day3, part2)] +fn part2(input: &str) -> i64 { + Regex::new(r"mul\((?[0-9]{1,3}),(?[0-9]{1,3})\)|do\(\)|don't\(\)") + .unwrap() + .captures_iter(input) + .fold((true, 0i64), |a, c| match c.get(0).unwrap().as_str() { + "do()" => (true, a.1), + "don't()" => (false, a.1), + _ => { + if a.0 { + ( + a.0, + a.1 + c.get(1).unwrap().as_str().parse::().unwrap() + * c.get(2).unwrap().as_str().parse::().unwrap(), + ) + } else { + a + } + } + }) + .1 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_example() { + assert_eq!( + part1(&parse( + "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5)) +" + )), + 161 + ); + } + + #[test] + fn part2_example() { + assert_eq!( + part2(&parse( + "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))" + )), + 48 + ); + } +} diff --git a/src/day4.rs b/src/day4.rs new file mode 100644 index 0000000..3903882 --- /dev/null +++ b/src/day4.rs @@ -0,0 +1,31 @@ +use aoc_runner_derive::{aoc, aoc_generator}; +#[aoc_generator(day4)] +fn parse(input: &str) -> String { + todo!() +} + +#[aoc(day4, part1)] +fn part1(input: &str) -> String { + todo!() +} + +#[aoc(day4, part2)] +fn part2(input: &str) -> String { + todo!() +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_example() { + assert_eq!(part1(&parse("")), ""); + } + + #[test] + fn part2_example() { + assert_eq!(part2(&parse("")), ""); + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..998b5a1 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,11 @@ +mod day4; +mod day3; +mod day1; +mod day2; + +extern crate aoc_runner; + +#[macro_use] +extern crate aoc_runner_derive; + +aoc_lib! {year = 2024}