From 16ed2a8caec709bec777b27a815f392c7a43db1e Mon Sep 17 00:00:00 2001 From: Fabian Schmidt Date: Mon, 4 Nov 2024 12:44:22 +0100 Subject: [PATCH] y2015d18 --- y2015/src/bin/d15.rs | 4 +- y2015/src/bin/d18.rs | 4 +- y2015/src/days/d18.rs | 171 +++++++++++++++++++++++++++++++++++++++--- y2015/src/days/mod.rs | 13 +--- 4 files changed, 169 insertions(+), 23 deletions(-) diff --git a/y2015/src/bin/d15.rs b/y2015/src/bin/d15.rs index 8d30aeb..6b9c277 100644 --- a/y2015/src/bin/d15.rs +++ b/y2015/src/bin/d15.rs @@ -14,8 +14,8 @@ fn part1() { } fn part2() { - let root = env!("CARGO_MANIFEST_DIR"); - let content = fs::read_to_string(format!("{root}/resources/15_input.txt")).unwrap(); + //let root = env!("CARGO_MANIFEST_DIR"); + //let content = fs::read_to_string(format!("{root}/resources/15_input.txt")).unwrap(); // change comments in part1 //println!("{}", d15::process_part2(&content)); } diff --git a/y2015/src/bin/d18.rs b/y2015/src/bin/d18.rs index fb3f4d5..ad1e0bd 100644 --- a/y2015/src/bin/d18.rs +++ b/y2015/src/bin/d18.rs @@ -10,11 +10,11 @@ fn main() { fn part1() { let root = env!("CARGO_MANIFEST_DIR"); let content = fs::read_to_string(format!("{root}/resources/18_input.txt")).unwrap(); - println!("{}", d18::process_part1(&content)); + println!("{}", d18::process_part1(&content, 100)); } fn part2() { let root = env!("CARGO_MANIFEST_DIR"); let content = fs::read_to_string(format!("{root}/resources/18_input.txt")).unwrap(); - println!("{}", d18::process_part2(&content)); + println!("{}", d18::process_part2(&content, 100)); } diff --git a/y2015/src/days/d18.rs b/y2015/src/days/d18.rs index 9025dcc..de59209 100644 --- a/y2015/src/days/d18.rs +++ b/y2015/src/days/d18.rs @@ -1,26 +1,179 @@ -pub fn process_part1(input: &str) -> i32 { - 0 +use core::panic; + +pub fn process_part1(input: &str, steps: u32) -> i32 { + let mut grid = input + .lines() + .map(|line| line.chars().map(Light::from).collect::>()) + .collect::>>(); + let height = grid.len(); + let width = grid[0].len(); + let mut new_grid = vec![vec![Light::Off; width]; height]; + for _step in 0..steps { + for (y, grid_line) in grid.iter().enumerate() { + for (x, light) in grid_line.iter().enumerate() { + let neighbors = Light::get_neighbors(grid.clone(), (x, y)); + new_grid[y][x] = light.new_state(neighbors); + } + } + grid = new_grid.clone(); + } + grid.iter() + .map(|line| { + line.iter() + .map(|&light| if light == Light::On { 1 } else { 0 }) + .sum::() + }) + .sum() } -pub fn process_part2(input: &str) -> i32 { - 0 +pub fn process_part2(input: &str, steps: u32) -> i32 { + let mut grid = input + .lines() + .map(|line| line.chars().map(Light::from).collect::>()) + .collect::>>(); + let height = grid.len(); + let width = grid[0].len(); + let corners = vec![ + (0, 0), + (width - 1, 0), + (0, height - 1), + (width - 1, height - 1), + ]; + for (corner_x, corner_y) in corners.clone() { + grid[corner_y][corner_x] = Light::On; + } + let mut new_grid = vec![vec![Light::Off; width]; height]; + for _step in 0..steps { + for (y, grid_line) in grid.iter().enumerate() { + for (x, light) in grid_line.iter().enumerate() { + let neighbors = Light::get_neighbors(grid.clone(), (x, y)); + new_grid[y][x] = light.new_state(neighbors); + } + } + grid = new_grid.clone(); + for (corner_x, corner_y) in corners.clone() { + grid[corner_y][corner_x] = Light::On; + } + } + grid.iter() + .map(|line| { + line.iter() + .map(|&light| if light == Light::On { 1 } else { 0 }) + .sum::() + }) + .sum() +} + +#[derive(Clone, Copy, PartialEq, Eq)] +enum Light { + On, + Off, +} + +impl Light { + fn new_state(self, neighbors: Vec) -> Self { + let mut light = self; + match self { + Light::On => { + if ![2, 3].contains(&Self::count_on(neighbors)) { + light = Light::Off; + } + } + Light::Off => { + if Self::count_on(neighbors) == 3 { + light = Light::On; + } + } + }; + light + } + + fn count_on(neighbors: Vec) -> u32 { + neighbors + .iter() + .map(|&light| if light == Light::On { 1 } else { 0 }) + .sum() + } + + fn get_neighbors(grid: Vec>, coords: (usize, usize)) -> Vec { + let relative_coords = vec![ + (-1, -1), + (0, -1), + (1, -1), + (-1, 0), + (1, 0), + (-1, 1), + (0, 1), + (1, 1), + ]; + let height = grid.len(); + let width = grid[0].len(); + let (x, y) = coords; + let mut neighbors = Vec::new(); + for (relative_x, relative_y) in relative_coords { + let neighbor_x = x.checked_add_signed(relative_x); + if neighbor_x.is_none() { + continue; + } + let neighbor_x = neighbor_x.unwrap(); + let neighbor_y = y.checked_add_signed(relative_y); + if neighbor_y.is_none() { + continue; + } + let neighbor_y = neighbor_y.unwrap(); + if neighbor_x >= width || neighbor_y >= height { + continue; + } + neighbors.push(grid[neighbor_y][neighbor_x]); + } + neighbors + } +} + +impl From for Light { + fn from(value: char) -> Self { + match value { + '#' => Light::On, + '.' => Light::Off, + _ => panic!("Wrong character"), + } + } +} + +#[allow(unused)] +fn print_grid(grid: Vec>) { + grid.iter().for_each(|line| { + line.iter().for_each(|&light| { + if light == Light::On { + print!("#"); + } else { + print!("."); + } + }); + println!(); + }); } #[cfg(test)] mod tests { use super::*; - const INPUT: &str = "{{EXAMPLE}}"; + const INPUT: &str = ".#.#.# +...##. +#....# +..#... +#.#..# +####.."; #[test] fn part1() { - let result = process_part1(INPUT); - assert_eq!(result, 0); + let result = process_part1(INPUT, 4); + assert_eq!(result, 4); } #[test] fn part2() { - let result = process_part2(INPUT); - assert_eq!(result, 0); + let result = process_part2(INPUT, 5); + assert_eq!(result, 17); } } diff --git a/y2015/src/days/mod.rs b/y2015/src/days/mod.rs index 0e75767..592f839 100644 --- a/y2015/src/days/mod.rs +++ b/y2015/src/days/mod.rs @@ -5,6 +5,9 @@ pub mod d12; pub mod d13; pub mod d14; pub mod d15; +pub mod d16; +pub mod d17; +pub mod d18; pub mod d2; pub mod d3; pub mod d4; @@ -13,13 +16,3 @@ pub mod d6; pub mod d7; pub mod d8; pub mod d9; - -pub mod d16; - -pub mod d17; - -pub mod d18; - -pub mod d18; - -pub mod d18;