day3: add clever solution

This commit is contained in:
2025-12-03 00:46:44 -08:00
parent f89bbf2bff
commit 6888466105
2 changed files with 56 additions and 17 deletions

View File

@@ -1,5 +1,6 @@
use aoc_runner_derive::{aoc, aoc_generator};
use memoize::memoize;
use misc::POW10;
#[aoc_generator(day3)]
fn parse(input: &str) -> Vec<Vec<u8>> {
@@ -17,33 +18,47 @@ fn max_joltage(bank: Vec<u8>, n: usize) -> u64 {
(0..bank.len() - n + 1)
.map(|start| {
bank[start] as u64 * 10u64.pow(n as u32 - 1)
+ max_joltage(bank[start + 1..].to_vec(), n - 1)
bank[start] as u64 * POW10[n - 1] + max_joltage(bank[start + 1..].to_vec(), n - 1)
})
.max()
.unwrap()
// let mut max = 0;
// for start in 0..bank.len() - n + 1 {
// let cur = bank[start] as u64 * 10u64.pow(n as u32 - 1)
// + *bank[start + 1..].iter().max().unwrap() as u64;
// if cur > max {
// max = cur
// }
// }
// max
}
#[aoc(day3, part1)]
fn max_joltage_2(bank: &[u8], n: usize) -> u64 {
if n == 1 {
return *bank.iter().max().unwrap() as u64;
}
let choices = &bank[..bank.len() - (n - 1)];
// Note: can't use position_max() here since it returns the _last_ instance and we need the _first_.
// get the max, then find the first instance of that value. There is definitely a one-pass solution.
let max = choices.iter().max().unwrap();
let choice = choices.iter().position(|n| max == n).unwrap();
let rest = &bank[choice + 1..];
bank[choice] as u64 * POW10[n - 1] + max_joltage_2(rest, n - 1)
}
#[aoc(day3, part1, Brute)]
fn part1(input: &[Vec<u8>]) -> u64 {
input.iter().map(|bank| max_joltage(bank.clone(), 2)).sum()
}
#[aoc(day3, part2)]
#[aoc(day3, part2, Brute)]
fn part2(input: &[Vec<u8>]) -> u64 {
input.iter().map(|bank| max_joltage(bank.clone(), 12)).sum()
}
#[aoc(day3, part1, Smart)]
fn part1_smart(input: &[Vec<u8>]) -> u64 {
input.iter().map(|bank| max_joltage_2(bank, 2)).sum()
}
#[aoc(day3, part2, Smart)]
fn part2_smart(input: &[Vec<u8>]) -> u64 {
input.iter().map(|bank| max_joltage_2(bank, 12)).sum()
}
#[cfg(test)]
mod tests {
use super::*;
@@ -62,4 +77,14 @@ mod tests {
fn part2_example() {
assert_eq!(part2(&parse(EXAMPLE)), 3121910778619);
}
#[test]
fn part1_smart_example() {
assert_eq!(part1_smart(&parse(EXAMPLE)), 357);
}
#[test]
fn part2_smart_example() {
assert_eq!(part2_smart(&parse(EXAMPLE)), 3121910778619);
}
}