2025-12-19 14:51:36 +00:00
|
|
|
use crate::puzzle::Puzzle;
|
|
|
|
|
use nom::{
|
|
|
|
|
Parser,
|
|
|
|
|
character::complete::{newline, satisfy},
|
|
|
|
|
combinator::eof,
|
|
|
|
|
error::Error,
|
|
|
|
|
multi::{many1, separated_list1},
|
|
|
|
|
sequence::terminated,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pub const PUZZLE: Puzzle<Vec<Vec<u8>>, 2> = Puzzle {
|
|
|
|
|
number: 3,
|
2026-01-12 22:27:41 +00:00
|
|
|
parser: |_, input| {
|
2025-12-19 14:51:36 +00:00
|
|
|
terminated::<_, _, Error<&str>, _, _>(
|
|
|
|
|
terminated(
|
|
|
|
|
separated_list1(
|
|
|
|
|
newline,
|
|
|
|
|
many1(satisfy(|c| c.is_digit(10)).map(|c| c as u8 - '0' as u8)),
|
|
|
|
|
),
|
|
|
|
|
newline,
|
|
|
|
|
),
|
|
|
|
|
eof,
|
|
|
|
|
)
|
|
|
|
|
.parse(input)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.1
|
|
|
|
|
},
|
|
|
|
|
parts: [
|
|
|
|
|
|input| {
|
|
|
|
|
input
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|bank| {
|
|
|
|
|
digits_to_int(&max_batteries(2, &bank).expect("battery list too short"))
|
|
|
|
|
})
|
|
|
|
|
.sum::<usize>()
|
|
|
|
|
.to_string()
|
|
|
|
|
},
|
|
|
|
|
|input| {
|
|
|
|
|
input
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|bank| {
|
|
|
|
|
digits_to_int(&max_batteries(12, &bank).expect("battery list too short"))
|
|
|
|
|
})
|
|
|
|
|
.sum::<usize>()
|
|
|
|
|
.to_string()
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
fn max_batteries(n: usize, v: &[u8]) -> Option<Vec<u8>> {
|
|
|
|
|
let mut result = Vec::with_capacity(n);
|
|
|
|
|
let mut remaining = n;
|
|
|
|
|
let mut slice = v;
|
|
|
|
|
while remaining > 0 {
|
2025-12-19 15:34:13 +00:00
|
|
|
match find_max(&slice[..slice.len() - remaining + 1]) {
|
2025-12-19 15:56:04 +00:00
|
|
|
Some((i, b)) => {
|
2025-12-19 15:36:17 +00:00
|
|
|
result.push(*b);
|
2025-12-19 15:34:13 +00:00
|
|
|
remaining -= 1;
|
|
|
|
|
slice = &slice[i + 1..];
|
|
|
|
|
}
|
|
|
|
|
None => return None,
|
2025-12-19 15:14:39 +00:00
|
|
|
}
|
2025-12-19 14:51:36 +00:00
|
|
|
}
|
|
|
|
|
Some(result)
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-22 14:53:22 +00:00
|
|
|
fn find_max<A: Ord>(v: &[A]) -> Option<(usize, &A)> {
|
2025-12-19 15:56:04 +00:00
|
|
|
v.iter().enumerate().rev().max_by_key(|x| x.1)
|
2025-12-19 14:51:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn digits_to_int(digits: &[u8]) -> usize {
|
|
|
|
|
digits.iter().fold(0, |acc, &d| acc * 10 + (d as usize))
|
|
|
|
|
}
|