day3: add clever solution
This commit is contained in:
53
src/day3.rs
53
src/day3.rs
@@ -1,5 +1,6 @@
|
|||||||
use aoc_runner_derive::{aoc, aoc_generator};
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
use memoize::memoize;
|
use memoize::memoize;
|
||||||
|
use misc::POW10;
|
||||||
|
|
||||||
#[aoc_generator(day3)]
|
#[aoc_generator(day3)]
|
||||||
fn parse(input: &str) -> Vec<Vec<u8>> {
|
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)
|
(0..bank.len() - n + 1)
|
||||||
.map(|start| {
|
.map(|start| {
|
||||||
bank[start] as u64 * 10u64.pow(n as u32 - 1)
|
bank[start] as u64 * POW10[n - 1] + max_joltage(bank[start + 1..].to_vec(), n - 1)
|
||||||
+ max_joltage(bank[start + 1..].to_vec(), n - 1)
|
|
||||||
})
|
})
|
||||||
.max()
|
.max()
|
||||||
.unwrap()
|
.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 {
|
fn part1(input: &[Vec<u8>]) -> u64 {
|
||||||
input.iter().map(|bank| max_joltage(bank.clone(), 2)).sum()
|
input.iter().map(|bank| max_joltage(bank.clone(), 2)).sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[aoc(day3, part2)]
|
#[aoc(day3, part2, Brute)]
|
||||||
fn part2(input: &[Vec<u8>]) -> u64 {
|
fn part2(input: &[Vec<u8>]) -> u64 {
|
||||||
input.iter().map(|bank| max_joltage(bank.clone(), 12)).sum()
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -62,4 +77,14 @@ mod tests {
|
|||||||
fn part2_example() {
|
fn part2_example() {
|
||||||
assert_eq!(part2(&parse(EXAMPLE)), 3121910778619);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,19 @@ use num_traits::Signed;
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::ops::{Add, AddAssign};
|
use std::ops::{Add, AddAssign};
|
||||||
|
|
||||||
|
const POW10MAX: usize = u64::MAX.ilog10() as usize;
|
||||||
|
pub const POW10: [u64; POW10MAX] = pow10_lut();
|
||||||
|
|
||||||
|
const fn pow10_lut<const N: usize>() -> [u64; N] {
|
||||||
|
let mut res = [0; N];
|
||||||
|
let mut i = 0;
|
||||||
|
while i < N {
|
||||||
|
res[i] = 10u64.pow(i as u32);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
/// Wrapped signed integer with custom upper bound with wrapping of 0s to the upper bound
|
/// Wrapped signed integer with custom upper bound with wrapping of 0s to the upper bound
|
||||||
#[derive(Eq, Clone, Copy)]
|
#[derive(Eq, Clone, Copy)]
|
||||||
pub struct CustomWrapped<T: Signed + Copy> {
|
pub struct CustomWrapped<T: Signed + Copy> {
|
||||||
@@ -91,8 +104,9 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn it_works() {
|
fn test_pow10() {
|
||||||
let result = add(2, 2);
|
for i in 0..POW10MAX {
|
||||||
assert_eq!(result, 4);
|
assert_eq!(POW10[i], 10u64.pow(i as u32))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user