use itertools::Itertools; fn neighbors(grid: &Vec>, position: (isize, isize)) -> i32 { let width = grid[0].len() as isize; let height = grid.len() as isize; let mut num_tp = 0; for y_offset in -1..=1 { for x_offset in -1..=1 { let search_position = (position.0 + x_offset, position.1 + y_offset); if search_position == position || search_position.0 < 0 || search_position.0 >= width || search_position.1 < 0 || search_position.1 >= height { continue; } let cell = grid[search_position.1 as usize][search_position.0 as usize]; if cell == '@' { num_tp += 1; } } } num_tp } pub fn process_part1(input: &str) -> i32 { let grid = input .lines() .map(|line| line.chars().collect_vec()) .collect_vec(); let width = grid[0].len() as isize; let height = grid.len() as isize; let mut accessible_tp = 0; for y in 0..height { for x in 0..width { if grid[y as usize][x as usize] != '@' { continue; } let neighbors = neighbors(&grid, (x, y)); if neighbors < 4 { accessible_tp += 1; } } } accessible_tp } pub fn process_part2(input: &str) -> i32 { let mut grid = input .lines() .map(|line| line.chars().collect_vec()) .collect_vec(); let width = grid[0].len() as isize; let height = grid.len() as isize; let mut accessible_tp_total = 0; loop { let mut accessible_tp = 0; let mut new_grid = grid.clone(); for y in 0..height { for x in 0..width { if grid[y as usize][x as usize] != '@' { continue; } let neighbors = neighbors(&grid, (x, y)); if neighbors < 4 { accessible_tp += 1; new_grid[y as usize][x as usize] = '.'; } else { new_grid[y as usize][x as usize] = '@'; } } } if accessible_tp == 0 { break; } grid = new_grid; accessible_tp_total += accessible_tp; } accessible_tp_total } #[cfg(test)] mod tests { use super::*; const INPUT: &str = "..@@.@@@@. @@@.@.@.@@ @@@@@.@.@@ @.@@@@..@. @@.@@@@.@@ .@@@@@@@.@ .@.@.@.@@@ @.@@@.@@@@ .@@@@@@@@. @.@.@@@.@."; #[test] fn part1() { let result = process_part1(INPUT); assert_eq!(result, 13); } #[test] fn part2() { let result = process_part2(INPUT); assert_eq!(result, 43); } }