summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReiner Herrmann <reiner@reiner-h.de>2023-12-15 13:28:54 +0100
committerReiner Herrmann <reiner@reiner-h.de>2023-12-15 13:28:54 +0100
commit4a0db8a0e353f14554482981651a5d75f7f78e7e (patch)
tree29e23bda68686d4a77250c0fd9007456ffec8fb5
parent60f3cb8d528318a1f4411c77738cf56e5dc1f693 (diff)
day15 solution 2
-rw-r--r--src/bin/day15.rs79
1 files changed, 74 insertions, 5 deletions
diff --git a/src/bin/day15.rs b/src/bin/day15.rs
index 648534a..2b3b04a 100644
--- a/src/bin/day15.rs
+++ b/src/bin/day15.rs
@@ -1,16 +1,18 @@
+use std::collections::VecDeque;
+
static DAY: u8 = 15;
fn main() {
let input = advent::read_file(DAY);
println!("{DAY}a: {}", hash_sum(&input));
- println!("{DAY}b: {}", 0);
+ println!("{DAY}b: {}", focusing_power(&input));
}
-fn hash(input: &str) -> u32 {
+fn hash(input: &str) -> usize {
let mut value = 0;
for c in input.chars() {
- value += c as u32;
+ value += c as usize;
value *= 17;
value %= 256;
}
@@ -18,10 +20,76 @@ fn hash(input: &str) -> u32 {
value
}
-fn hash_sum(input: &str) -> u32 {
+#[derive(Clone, Debug)]
+struct Lens {
+ label: String,
+ focal_length: usize,
+}
+
+enum Operation {
+ Assign(Lens),
+ Remove(String),
+}
+
+impl Operation {
+ fn from(input: &str) -> Operation {
+ if let Some((label, value)) = input.split_once('=') {
+ Operation::Assign(Lens {
+ label: label.to_string(),
+ focal_length: value.parse().unwrap()
+ })
+ } else if let Some((label, _)) = input.split_once('-') {
+ Operation::Remove(label.to_string())
+ } else {
+ panic!("invalid operation");
+ }
+ }
+
+ fn label(&self) -> String {
+ match self {
+ Operation::Assign(lens) => lens.label.clone(),
+ Operation::Remove(label) => label.to_string(),
+ }
+ }
+}
+
+fn hash_sum(input: &str) -> usize {
let input = input.trim_end();
input.split(',')
- .map(|x| hash(x))
+ .map(hash)
+ .sum()
+}
+
+fn init_sequence(boxes: &mut [VecDeque::<Lens>], operations: &[Operation]) {
+ for operation in operations {
+ let box_nr = hash(&operation.label());
+ match operation {
+ Operation::Assign(lens) => {
+ if let Some(boxed_lens) = boxes[box_nr].iter_mut().find(|l| l.label == lens.label) {
+ boxed_lens.focal_length = lens.focal_length;
+ } else {
+ boxes[box_nr].push_back(lens.clone());
+ }
+ },
+ Operation::Remove(label) => {
+ boxes[box_nr].retain(|lens| lens.label != *label);
+ }
+ }
+ }
+}
+
+fn focusing_power(input: &str) -> usize {
+ let input = input.trim_end();
+ let operations = input.split(',')
+ .map(Operation::from)
+ .collect::<Vec<_>>();
+
+ let mut boxes = vec![VecDeque::<Lens>::new(); 256];
+ init_sequence(&mut boxes, &operations);
+
+ boxes.iter()
+ .enumerate()
+ .map(|(box_nr, lenses)| lenses.iter().enumerate().map(|(slot, lens)| (box_nr + 1) * (slot + 1) * lens.focal_length).sum::<usize>())
.sum()
}
@@ -34,5 +102,6 @@ mod tests {
let input = "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7";
assert_eq!(hash("HASH"), 52);
assert_eq!(hash_sum(input), 1320);
+ assert_eq!(focusing_power(input), 145);
}
}