From 3e9ff4ded0c36462c34816fab0b047f3ef6ee34c Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Sat, 7 Dec 2024 14:50:59 +0100 Subject: [PATCH] optimize d7p2 --- 2024/day07/src/lib.rs | 79 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/2024/day07/src/lib.rs b/2024/day07/src/lib.rs index d39776b..4e68e85 100644 --- a/2024/day07/src/lib.rs +++ b/2024/day07/src/lib.rs @@ -14,6 +14,8 @@ helper::define_variants! { part2 { basic => crate::part2,sample_count=500; no_string_fmt => crate::part2_no_string_fmt,sample_count=1000; + order => crate::part2_order,sample_count=1000; + parsing => crate::part2_parsing,sample_count=5000; } } @@ -127,6 +129,81 @@ fn part2_no_string_fmt(input: &str) -> u64 { total } +fn part2_order(input: &str) -> u64 { + let mut total = 0; + for line in input.lines() { + let (result, values) = line.split_once(": ").unwrap(); + let result = parse_unwrap(result); + let values = values + .split(" ") + .map(|val| (val, parse_unwrap(val))) + .collect::>(); + + fn does_work(values: &[(&str, u64)], result: u64) -> bool { + if values.len() == 1 { + return values[0].1 == result; + } + + let (l_str, l) = *values.last().unwrap(); + let next = &values[..(values.len() - 1)]; + let thousand = 10_u64.pow(l_str.len() as u32); + + let concat_works = result % thousand == l; + let mul_works = result % l == 0; + let sub_works = l <= result; + + // Concat is the least common, so doing it first helps remove the most possibilities. + false + || (concat_works && does_work(next, result / thousand)) + || (mul_works && does_work(next, result / l)) + || (sub_works && does_work(next, result - l)) + } + + if does_work(&values, result) { + total += result; + } + } + total +} + +fn part2_parsing(input: &str) -> u64 { + let mut total = 0; + + let mut values = Vec::new(); + + for line in input.lines() { + values.clear(); + let (result, values_str) = line.split_once(": ").unwrap(); + let result = parse_unwrap(result); + values.extend(values_str.split(' ').map(|val| (val, parse_unwrap(val)))); + + fn does_work(values: &[(&str, u64)], result: u64) -> bool { + if values.len() == 1 { + return values[0].1 == result; + } + + let (l_str, l) = *values.last().unwrap(); + let next = &values[..(values.len() - 1)]; + let thousand = 10_u64.pow(l_str.len() as u32); + + let concat_works = result % thousand == l; + let mul_works = result % l == 0; + let sub_works = l <= result; + + // Concat is the least common, so doing it first helps remove the most possibilities. + false + || (concat_works && does_work(next, result / thousand)) + || (mul_works && does_work(next, result / l)) + || (sub_works && does_work(next, result - l)) + } + + if does_work(&values, result) { + total += result; + } + } + total +} + helper::tests! { day07 Day07; part1 { @@ -135,7 +212,7 @@ helper::tests! { } part2 { small => 11387; - default => 0; + default => 146111650210682; } } helper::benchmarks! {}