From 9e2e03812366e39ddc84fb80b5cc90a69a9eb936 Mon Sep 17 00:00:00 2001 From: ironsm4sh <ironsm4sh@ironsm4sh.nl> Date: Fri, 23 Dec 2022 08:04:57 +0100 Subject: [PATCH] Day 23 --- Cargo.toml | 4 + input/day23.txt | 71 ++++++++++++++++++ src/day23.rs | 191 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 266 insertions(+) create mode 100644 input/day23.txt create mode 100644 src/day23.rs diff --git a/Cargo.toml b/Cargo.toml index ab333f0..b99ec3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,3 +94,7 @@ path = "src/day21.rs" [[bin]] name = "day22" path = "src/day22.rs" + +[[bin]] +name = "day23" +path = "src/day23.rs" diff --git a/input/day23.txt b/input/day23.txt new file mode 100644 index 0000000..9db15fc --- /dev/null +++ b/input/day23.txt @@ -0,0 +1,71 @@ +.###.....#...###.##.#....##.#.#####.#####.#.##.....##..#.#.#.##.#.#.... +#..#####....###.####.###...#..#...#......#..###...#....#####.####..##.# +#.###..#####..#..#...#####...###...###..##.....##.##..#...##....####..# +.###.##..##....#...#..#..#..#...###.###.#.#...#.###..##.###...#.....##. +#.........#.#..#..#####.#.###.....#...#..#..##..#.#..#.##..##..#...#### +..##.#####..########..##..##.#....#.#....#.###.#...#.#####...###...##.# +#.#..#.#..####.##.#.##.##.#.##.#.##...#.##...##.##.##...##...#..##.#.#. +##...#...##.#####.#######..##...######.....####.#...####.##....#.###... +...#####.......##.###.#.##..###.....##.#..####...#.#..#...##.#.##.#..#. +##..####..######.##......###...#...#.#.#.#....###.##.###...##.#.####... +.#..#..#.#.##..#....##..##.#.##.#...#..##.###...#####...##.###.#..###.# +#....###.####.###.#..####.#...#..##.#.....##..#.###.##.#.###########..# +##..##..#...#..###.###..#.##.######.#......###..####.#..#.#.##..#..###. +....#.....#.#.#..##.#####.####.##.###..####.#...#.##.####..###..#.#...# +..###........#.#.#.#....##.##..#..##..#.###.#....##.#....###..#..####.. +##....##.##.####.#..#.#..#...#.#....###..#..##.#...#....##.#.######.#.. +.#.#.#...#....#...##.###..#.#.#.#........#.##...####.#....######.###..# +.##...#.###.#.#.##..###.#..#.#.###.#####..##..#####..###.##.###..#####. +.#.##.###..#.....#.......##.##..##..#...#...####..#.#......###.#.#.##.. +#######.#.#..#######....#######.##...###...###.#.#.##...###..#..##.#.## +.#..#..#.######..####.######..##.#.####..##..###.#...#.##...###.#.#..## +##..#.#.#..##.#.#.##.#.....##.#.###..##..###.##.##...#..###.#..#....... +###..#...#...#...#.#.###.#######.#..##..##.#.##.##.##.#.##.##.#.####... +##...######.###....#..#.#.#.#.#......#.##.#.#.##.#...#.###.##.###.##..# +.####..#.#.##..#.....#..###..##...##...#.#..##...###..#...######.#...#. +.###...##...##.#.###....#.#...#..##.#.#.##.#######..#......#...##..#### +#.#.#.###.#.#..#.#.#######.#..##.....#.#####.#..##..##.#....##...#..#.# +##.###...##........##.###....##.###..####..#..#..#...#..#.#.##......#.. +##...#.#...##.#..#.##...###.##.####.#.##.###..#.#....#...##.##.###..##. +..##..#..#.####...#.#.######.#..##..#####.#..###....##.#.#.#.##..####.. +####..#....####....##..###..#####.##.#.#.###..#.#.##..#.#....##.###..## +....##..#....#####...###..###..#.##.....#.#.#..###.####.##....#.#.#.### +.#.##.##.#..####..#.##........####.#.#.###.##.##.#..###....##..##..#.#. +.###.##.##.#....#...####..#..#..#..###.##...##.#.#.#.##...#.#.#..#..#.. +#......#.##....####.####...#.#.###..#.#.#.#.#..#.....#.##.#...##..#.... +#.#.#....###.#....###..####...##.##....#..####..#....##.#..####..#..### +##.#....##.##.....#..######..#.#..##..#.#...##.#.#.#####...#.#.#.#.###. +...#.###.##....##.#.###.##.......#..#####..#.#.#.##..####.#...###.#.#.. +##......##...###.....######.#.######.#.##.#.#...##.##..#..#.####...###. +.##.#..######.#.##...##.....##..##.##...##.#.###.#..###......##...#.#.. +.....#####.......##.##.####..#.#..##..#.###.#.#.#..##.####..#.#.##..##. +....###.######.#.##..######..####...##..##....#..##.#.#.....#.###..#### +.#.#..#.#.#...##...##.#....#.#..###.###.##.#.###.#.##..#..#....##.##### +..##.#...######.#..##...##.#.###.#...##..#.#####..#..###.#.#.#..###...# +....##..#.#..........#..##.#.####..##...#.#...##.###...##....#######..# +##.#.#..####.###.#.#....#.#..#..########.##..##.####.#.#.#..##...#.#.## +..#.#.#...#.#..#....#..##.#..#.##....#....##.###..###....#.###.#.#..### +.##.....####..#....####.##...#..##....##..##.....##.###.##.#...##.###.. +.##.....##.#####..#####.####.######....#.###.#.###.##.#.#......#....### +...#.#..####.#.###.#.....##.##.##.##....##....###....##.##........####. +.##.###.##.##.##...#..#....#..##.###..##..#..#...#.#.##..##..#..#..#### +.#...#.......#.##.##....##.....#..##...###.#....#.###.#.#..####.#.#..## +.#..#..###.####..##.#.##..###.###..##....###.#...##.#.......#..##.#.#.. +.##.......#..###.##.##..######..##..###.#.######.####...####.....##..## +###..#..#...###.#..###..#.#.#.########...#.......#.#.#.#..#.#.##.###..# +#.#..#...#...##..#.##..#..#............#..#.#..####.###.#######.###...# +#...#.##.###.##.....#.########..####.###.#..#..####.##.#...##..#..##.#. +......####...#.#.###.##..#.##.##..#.#.#.....#...#.##.#.#.##..##.###..#. +.#.#.##.#.##.#.#.#.#...#.###.#....#..####.###.....#.###.##.##.#.##.###. +#####.#..##.##....##..####....#.#..#..#..#.#.###.#.#..####.####...#.##. +#...##..###..####.#......#.######...#.####....##....#.##.....####.#.#.# +.#..##..#.######.#...#..#...########..#.#..#....#.##....#.#.##.####.... +###.#.##......##.#########.#.########...#...#.#..#....#..###.#.#..#..#. +.####..#.##...#.##..#.##.#.##.##...#..###.##.....#.##.#...####....###.# +#####...#...#..#.##.#..##.#.##..#.#......##.##.##..#.#.#.##.##..#...... +##.###....#..#......#.####..###.#.#.##...#..#.#.###....####.#.#..##.... +.#..##.######.##...#.#.##..#.###..##..##.##...###..#####.###....####### +#.#.....#..#...#.........#.####.#...#....#.###.#.#..####....#.##.##.#.# +..###...###.##.##.#..######..###.###..#.##..###...###.....###.##.###### +########......#.#..#.#.##..##.##....##.#.#.###..#.#...#...#.#..##....## +.##...##...#..#...#..#...#..#..##.##.#...#.###....#..#.##......#.#....# \ No newline at end of file diff --git a/src/day23.rs b/src/day23.rs new file mode 100644 index 0000000..4ac0686 --- /dev/null +++ b/src/day23.rs @@ -0,0 +1,191 @@ +use std::collections::{HashMap, HashSet, VecDeque}; +type Vec2 = (i32, i32); + +fn main() { + let mut world: HashMap<Vec2, Option<Vec2>> = HashMap::new(); + + let mut current = (0, 0); + for line in include_str!("../input/day23.txt").split('\n') { + for char in line.chars() { + match char { + '#' => Some(world.insert(current, None)), + _ => None, + }; + current.0 += 1; + } + current.0 = 0; + current.1 += 1; + } + + let mut instruction_order: VecDeque<char> = VecDeque::from(['N', 'S', 'W', 'E']); + + for _ in 0..10 { + let should_move = process_first_half(&mut world, &mut instruction_order); + if should_move { + world = process_second_half(&world); + continue; + } + break; + } + + let silver = get_empty_in_limits(&world); + println!("Part one: {silver}"); + + let mut round = 10; + loop { + let should_move = process_first_half(&mut world, &mut instruction_order); + round += 1; + if should_move { + world = process_second_half(&world); + continue; + } + break; + } + + println!("Part two: {round}"); +} + +fn process_second_half(world: &HashMap<Vec2, Option<Vec2>>) -> HashMap<Vec2, Option<Vec2>> { + let mut known: HashMap<Vec2, i32> = HashMap::new(); + for (pos, optional) in world.iter() { + if let Some(proposed_position) = optional { + let mut current = *known.get(&proposed_position).unwrap_or(&0); + current += 1; + known.insert(proposed_position.clone(), current); + } else { + known.insert(pos.clone(), 2); + } + } + + let mut new_world: HashMap<Vec2, Option<Vec2>> = HashMap::new(); + for (pos, optional) in world.iter() { + if let Some(proposed_position) = optional { + let elves = *known.get(&proposed_position).unwrap(); + if elves == 1 { + new_world.insert(proposed_position.clone(), None); + } else { + new_world.insert(pos.clone(), None); + } + } else { + new_world.insert(pos.clone(), None); + } + } + return new_world; +} + +fn process_first_half( + world: &mut HashMap<Vec2, Option<Vec2>>, + instruction_order: &mut VecDeque<char>, +) -> bool { + let north = vec![(0, -1), (-1, -1), (1, -1)]; + let south = vec![(0, 1), (-1, 1), (1, 1)]; + let east = vec![(1, 0), (1, -1), (1, 1)]; + let west = vec![(-1, 0), (-1, -1), (-1, 1)]; + let mut neighbors: Vec<Vec2> = Vec::new(); + neighbors.extend(north.iter()); + neighbors.extend(south.iter()); + neighbors.extend(east.iter()); + neighbors.extend(west.iter()); + + let instructions = vec![ + instruction_order.pop_front().unwrap(), + instruction_order.pop_front().unwrap(), + instruction_order.pop_front().unwrap(), + instruction_order.pop_front().unwrap(), + ]; + let mut known: HashSet<Vec2> = HashSet::new(); + for (pos, _) in world.iter() { + known.insert(pos.clone()); + } + let mut output = false; + for (pos, proposed_position) in world.iter_mut() { + let mut is_alone = true; + for neighbor in neighbors.iter() { + if known.contains(&(pos.0 + neighbor.0, pos.1 + neighbor.1)) { + is_alone = false; + break; + } + } + if is_alone { + continue; + } + + for instruction in instructions.iter() { + let to_check; + match instruction { + 'N' => to_check = &north, + 'E' => to_check = &east, + 'S' => to_check = &south, + 'W' => to_check = &west, + _ => panic!("Invalid instruction!"), + } + + let mut is_alone = true; + for neighbor in to_check { + if known.contains(&(pos.0 + neighbor.0, pos.1 + neighbor.1)) { + is_alone = false; + break; + } + } + if !is_alone { + continue; + } + + *proposed_position = Some((pos.0 + to_check[0].0, pos.1 + to_check[0].1)); + output = true; + break; + } + } + instruction_order.push_back(instructions[1]); + instruction_order.push_back(instructions[2]); + instruction_order.push_back(instructions[3]); + instruction_order.push_back(instructions[0]); + return output; +} + +fn get_empty_in_limits(world: &HashMap<Vec2, Option<Vec2>>) -> i32 { + let limits = get_limits(world); + let width = (limits.1 .0 - limits.0 .0) + 1; + let height = (limits.1 .1 - limits.0 .1) + 1; + return width * height - world.len() as i32; +} + +fn get_limits(world: &HashMap<Vec2, Option<Vec2>>) -> (Vec2, Vec2) { + let mut limits = ((0, 0), (0, 0)); + + for (pos, _) in world.iter() { + if pos.0 < limits.0 .0 { + limits.0 .0 = pos.0; + } + if pos.0 > limits.1 .0 { + limits.1 .0 = pos.0; + } + if pos.1 < limits.0 .1 { + limits.0 .1 = pos.1; + } + if pos.1 > limits.1 .1 { + limits.1 .1 = pos.1; + } + } + + return limits; +} + +#[allow(dead_code)] +fn print_world(world: &HashMap<Vec2, Option<Vec2>>) { + let limits = get_limits(world); + let mut output = String::new(); + output += "\n"; + for y in limits.0 .1..=limits.1 .1 { + for x in limits.0 .0..=limits.1 .0 { + let v = world.get(&(x, y)); + + match v { + Some(_) => output += "#", + None => output += ".", + } + } + output += "\n"; + } + println!("{output}"); +} -- GitLab