From 1f02ab5462e55119738945b60db3ac3fc42cc3be Mon Sep 17 00:00:00 2001 From: Hans Baker Date: Thu, 14 Dec 2023 23:07:22 -0800 Subject: [PATCH] day 15 in the books --- data/examples/15.txt | 1 + src/bin/15.rs | 93 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 data/examples/15.txt create mode 100644 src/bin/15.rs diff --git a/data/examples/15.txt b/data/examples/15.txt new file mode 100644 index 0000000..62f7ed0 --- /dev/null +++ b/data/examples/15.txt @@ -0,0 +1 @@ +rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7 \ No newline at end of file diff --git a/src/bin/15.rs b/src/bin/15.rs new file mode 100644 index 0000000..4ba2d33 --- /dev/null +++ b/src/bin/15.rs @@ -0,0 +1,93 @@ +advent_of_code::solution!(15); + +fn hash_it(s: &str) -> usize { + s.as_bytes() + .iter() + .map(|x| *x as usize) + .fold(0, |acc, x| (acc + x) * 17 % 256) +} + +pub fn part_one(input: &str) -> Option { + let sum = input + .lines() + .next() + .unwrap() + .split(',') + .map(hash_it) + .sum::(); + Some(sum as u64) +} + +enum Op { + Rem, + Set(usize), +} + +impl Op { + fn from(s: &str) -> Self { + match s.chars().next().unwrap() { + '-' => Self::Rem, + '=' => { + let num = &s[1..2] + .parse::() + .expect("= should be followed by number"); + Self::Set(*num) + } + _ => panic!("Unexpected op {}", s), + } + } +} + +pub fn part_two(input: &str) -> Option { + let mut boxes: Vec> = vec![Vec::new(); 256]; + input.lines().next().unwrap().split(',').for_each(|s| { + let len = if s.chars().last().unwrap() == '-' { + s.len() - 1 + } else { + s.len() - 2 + }; + let label = &s[0..len]; + let hash_val = hash_it(label); + let op = Op::from(&s[len..]); + if let Some(index) = boxes[hash_val].iter().position(|item| item.0 == label) { + match op { + Op::Rem => { + boxes[hash_val].remove(index); + } + Op::Set(x) => { + boxes[hash_val][index] = (label.to_owned(), x); + } + } + } else if let Op::Set(x) = op { + boxes[hash_val].push((label.to_owned(), x)); + } + }); + let sum = boxes + .iter() + .enumerate() + .map(|(num, v)| { + v.iter() + .enumerate() + .map(|(index, item)| (1 + num) * (1 + index) * item.1) + .sum::() + }) + .sum::(); + Some(sum as u64) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_one() { + let result = part_one(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, Some(1320)); + } + + #[test] + fn test_part_two() { + let result = part_two(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, Some(145)); + } +}