diff --git a/samples/day20.txt b/samples/day20.txt new file mode 100644 index 0000000..5cbf3d9 --- /dev/null +++ b/samples/day20.txt @@ -0,0 +1,7 @@ +1 +2 +-3 +3 +-2 +0 +4 \ No newline at end of file diff --git a/src/bin/day20.rs b/src/bin/day20.rs new file mode 100644 index 0000000..22f8ec8 --- /dev/null +++ b/src/bin/day20.rs @@ -0,0 +1,110 @@ +use aoc_2022::*; + +type Input = Vec; +type Output = i64; + +#[derive(Debug, Clone, PartialEq)] +struct Coordinate { + key: i64, + index: usize, + swapped: bool, +} + +impl Coordinate { + fn new(key: i64, index: usize) -> Self { + Self { + key, + index, + swapped: key == 0, + } + } + + fn reset(&self) -> Self { + Self { + swapped: self.key == 0, + ..*self + } + } +} + +fn index_of(vector: &[T], key: &T) -> Option { + vector + .iter() + .enumerate() + .find(|&(_, val)| key == val) + .map(|found| found.0) +} + +fn mix(order: &[Coordinate], mut coordinates: Input) -> Input { + let length: i64 = coordinates.len().try_into().unwrap(); + + for coordinate in order { + if coordinate.swapped { + continue; + } + + let old_idx = index_of(&coordinates, coordinate).unwrap(); + + let mut new_idx = (old_idx as i64 + coordinate.key) % (length - 1); + if new_idx < 0 { + new_idx += length - 1; + } + + let mut c = coordinates.remove(old_idx); + c.swapped = true; + coordinates.insert(new_idx as usize, c); + } + + coordinates.iter().map(Coordinate::reset).collect_vec() +} + +fn find_sum(mixed: &[Coordinate]) -> Output { + let mixed = mixed.iter().map(|c| c.key).collect_vec(); + let base_index = index_of(&mixed, &0).unwrap(); + + vec![1000, 2000, 3000] + .iter() + .map(|off| mixed[(base_index + off) % mixed.len()]) + .sum() +} + +struct Day20; +impl Solution for Day20 { + fn parse_input>(pathname: P) -> Input { + let coordinates: Vec = file_to_structs(pathname); + + coordinates + .iter() + .enumerate() + .map(|(i, key)| Coordinate::new(*key, i)) + .collect_vec() + } + + fn part_1(input: &Input) -> Output { + let order = input.clone(); + let mixed = mix(&order, input.clone()); + + find_sum(&mixed) + } + + fn part_2(input: &Input) -> Output { + let decryption_key = 811589153; + let with_decryption = input + .iter() + .cloned() + .map(|c| Coordinate::new(c.key * decryption_key, c.index)) + .collect_vec(); + + let order = with_decryption.clone(); + let mixed = (0..10).fold(with_decryption, |acc, _| mix(&order, acc)); + + find_sum(&mixed) + } +} + +fn main() -> Result<()> { + // Day20::run("sample") + Day20::main() +} + +test_sample!(day_20, Day20, 3, 1623178306);