diff --git a/src/day15.rs b/src/day15.rs new file mode 100644 index 0000000..c7440d3 --- /dev/null +++ b/src/day15.rs @@ -0,0 +1,95 @@ +use aoc_runner_derive::{aoc, aoc_generator}; + +#[aoc_generator(day15)] +fn parse(input: &str) -> Vec { + input.split(',').map(|x| x.into()).collect::>() +} + +#[aoc(day15, part1)] +fn part1(input: &Vec) -> u32 { + let mut total = 0; + for step in input { + total += hash(step); + } + + total +} + +fn hash(string: &str) -> u32 { + let mut cur_val = 0; + for char in string.chars() { + cur_val += char as u32; + cur_val *= 17; + cur_val = cur_val % 256; + } + cur_val +} + +#[aoc(day15, part2)] +fn part2(input: &Vec) -> usize { + let mut boxes: [Vec<(String, usize)>; 256] = + std::iter::repeat_with(|| Vec::with_capacity(input.len())) + .take(256) + .collect::>() + .try_into() + .unwrap(); + for step in input { + + + if let Some(dash) = step.find('-') { + let label = &step[0..dash]; + let box_number = hash(label) as usize; + if let Some(position) = boxes[box_number].iter().position(|(l, _)| *l == *label) { + boxes[box_number].remove(position); + } + } else if let Some(equal) = step.find('=') { + let label = &step[0..equal]; + let box_number = hash(label) as usize; + let focal_length = &step[equal + 1..].parse::().unwrap(); + if let Some(position) = boxes[box_number].iter().position(|(l, _)| *l == *label) { + let _ = std::mem::replace( + &mut boxes[box_number][position], + (label.clone().to_string(), *focal_length as usize), + ); + } else { + boxes[box_number].push((label.clone().to_string(), *focal_length as usize)); + } + } else { + panic!("invalid step AHHH {}", step) + } + } + + let mut total = 0; + + for (index, lens_box) in boxes.iter().enumerate() { + for (slot, (_, focal_len)) in lens_box.iter().enumerate() { + total += (index + 1) * (slot + 1) * focal_len; + } + } + + total +} + + +#[cfg(test)] +mod tests { + use super::*; + + const EX: &str = r"HASH"; + const EX_2: &str = r"rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7"; + + #[test] + fn part1_example() { + assert_eq!(part1(&parse(EX)), 52); + } + + #[test] + fn part1_example2() { + assert_eq!(part1(&parse(EX_2)), 1320); + } + + #[test] + fn part2_example2() { + assert_eq!(part2(&parse(EX_2)), 145); + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index ece7c82..792deb9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +mod day15; mod day14; mod day13; mod day12;