From 6d557c35cf3b4dea772a1b445a81f299f9084c33 Mon Sep 17 00:00:00 2001 From: Jan-Bulthuis Date: Sat, 7 Dec 2024 14:36:19 +0100 Subject: [PATCH] day7 --- aoc_2024/src/day7.rs | 90 ++++++++++++++++++++++++++++++++++++++++++++ aoc_2024/src/lib.rs | 7 ++-- 2 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 aoc_2024/src/day7.rs diff --git a/aoc_2024/src/day7.rs b/aoc_2024/src/day7.rs new file mode 100644 index 0000000..eb4ea98 --- /dev/null +++ b/aoc_2024/src/day7.rs @@ -0,0 +1,90 @@ +use aoc_runner_derive::{aoc, aoc_generator}; +use nom::{ + bytes::complete::tag, + character::complete::{newline, space1, u64 as parse_u64}, + error::Error, + multi::separated_list1, + sequence::separated_pair, +}; + +type Input = Vec<(u64, Vec)>; + +#[aoc_generator(day7)] +fn parse(input: &str) -> Input { + separated_list1( + newline::<&str, Error<&str>>, + separated_pair(parse_u64, tag(": "), separated_list1(space1, parse_u64)), + )(input) + .unwrap() + .1 +} + +#[aoc(day7, part1)] +fn part1(input: &Input) -> usize { + input + .iter() + .filter(|v| part1_test(v.1[0], v.0, &v.1[1..])) + .fold(0, |acc, v| acc + v.0 as usize) +} + +fn part1_test(curr: u64, target: u64, numbers: &[u64]) -> bool { + if curr > target { + false + } else if numbers.is_empty() { + curr == target + } else { + let num = numbers[0]; + let rest = &numbers[1..]; + part1_test(curr + num, target, rest) || part1_test(curr * num, target, rest) + } +} + +#[aoc(day7, part2)] +fn part2(input: &Input) -> usize { + input + .iter() + .filter(|v| part2_test(v.1[0], v.0, &v.1[1..])) + .fold(0, |acc, v| acc + v.0 as usize) +} + +fn concat(a: u64, b: u64) -> u64 { + let digits = b.ilog10() + 1; + a * 10u64.pow(digits) + b +} + +fn part2_test(curr: u64, target: u64, numbers: &[u64]) -> bool { + if curr > target { + false + } else if numbers.is_empty() { + curr == target + } else { + let num = numbers[0]; + let rest = &numbers[1..]; + part2_test(curr + num, target, rest) + || part2_test(curr * num, target, rest) + || part2_test(concat(curr, num), target, rest) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_example() { + assert_eq!(part1(&parse("190: 10 19\n3267: 81 40 27\n83: 17 5\n156: 15 6\n7290: 6 8 6 15\n161011: 16 10 13\n192: 17 8 14\n21037: 9 7 18 13\n292: 11 6 16 20")), 3749); + assert_eq!( + part1(&parse(include_str!("../input/2024/day7.txt"))), + 3598800864292 + ); + } + + #[test] + fn part2_example() { + assert_eq!(part2(&parse("190: 10 19\n3267: 81 40 27\n83: 17 5\n156: 15 6\n7290: 6 8 6 15\n161011: 16 10 13\n192: 17 8 14\n21037: 9 7 18 13\n292: 11 6 16 20")), 11387); + assert_eq!( + part2(&parse(include_str!("../input/2024/day7.txt"))), + 340362529351427 + ); + } +} diff --git a/aoc_2024/src/lib.rs b/aoc_2024/src/lib.rs index 23ec5de..06ec462 100644 --- a/aoc_2024/src/lib.rs +++ b/aoc_2024/src/lib.rs @@ -1,9 +1,10 @@ -mod day6; -mod day5; -mod day4; mod day1; mod day2; mod day3; +mod day4; +mod day5; +mod day6; +mod day7; extern crate aoc_runner;