diff options
Diffstat (limited to 'src/bin')
| -rw-r--r-- | src/bin/day18.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/bin/day18.rs b/src/bin/day18.rs new file mode 100644 index 0000000..36850eb --- /dev/null +++ b/src/bin/day18.rs @@ -0,0 +1,96 @@ +use std::collections::HashMap; + +fn main() { + let input = advent::read_lines(18); + println!("18a: {}", count_lights(&input, 100, false)); + println!("18b: {}", count_lights(&input, 100, true)); +} + +fn count_neighbors(grid: &HashMap<(isize, isize), bool>, pos: (isize, isize)) -> usize { + let mut count = 0; + for x in pos.0 - 1 ..= pos.0 + 1 { + for y in pos.1 - 1 ..= pos.1 + 1 { + if (x, y) == pos { + continue; + } + if let Some(true) = grid.get(&(x, y)) { + count += 1; + } + } + } + count +} + +fn stuck_grid(grid: &mut HashMap<(isize, isize), bool>, dim: isize) { + grid.insert((0, 0), true); + grid.insert((dim-1, dim-1), true); + grid.insert((0, dim-1), true); + grid.insert((dim-1, 0), true); +} + +fn step(grid: HashMap<(isize, isize), bool>, dim: usize, stuck: bool) -> HashMap<(isize, isize), bool> { + let mut next_grid = HashMap::new(); + + for y in 0 .. dim { + for x in 0 .. dim { + let pos = (x as isize, y as isize); + let val = *grid.get(&pos).unwrap(); + let neighbors = count_neighbors(&grid, pos); + + let new_val = match val { + true => [2, 3].contains(&neighbors), + false => neighbors == 3, + }; + next_grid.insert(pos, new_val); + } + } + if stuck { + stuck_grid(&mut next_grid, dim as isize); + } + + next_grid +} + +fn count_lights(input: &[String], steps: u16, stuck: bool) -> usize { + let dim = input.len(); + + let mut grid = HashMap::new(); + + for (y, line) in input.iter().enumerate() { + for (x, c) in line.chars().enumerate() { + let pos = (x as isize, y as isize); + match c { + '#' => grid.insert(pos, true), + '.' => grid.insert(pos, false), + _ => unimplemented!(), + }; + } + } + if stuck { + stuck_grid(&mut grid, dim as isize); + } + + for _ in 0 .. steps { + grid = step(grid, dim, stuck); + } + grid.values().filter(|&val| *val).count() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + let input = [ + ".#.#.#".to_string(), + "...##.".to_string(), + "#....#".to_string(), + "..#...".to_string(), + "#.#..#".to_string(), + "####..".to_string(), + ]; + assert_eq!(count_lights(&input, 4, false), 4); + assert_eq!(count_lights(&input, 5, true), 17); + } +} |
