From: alex Date: Thu, 21 Dec 2023 21:12:23 +0000 (+0100) Subject: Day21 - part 1 X-Git-Url: https://aoc.elinar.fr/?a=commitdiff_plain;h=dea57dbf09c6d388a40dfc9e38dbb6d77861f328;p=aoc_2023 Day21 - part 1 --- diff --git a/src/day21.rs b/src/day21.rs new file mode 100644 index 0000000..3806719 --- /dev/null +++ b/src/day21.rs @@ -0,0 +1,161 @@ +use std::io::Read; +use std::error::Error; +use std::fs::File; + +use std::collections::VecDeque; + +const END_STEP: u32 = 64; + +pub fn run(input_file: &str) -> Result<(), Box> { + let mut f = File::open(input_file)?; + let mut input = String::new(); + f.read_to_string(&mut input)?; + + let res = run_part1(&input, END_STEP)?; + println!("{res}"); + + let res = run_part2(&input)?; + println!("{res}"); + + Ok(()) +} + +#[derive(Debug)] +struct Puzzle { + map: Vec>, + seen_at_step: Vec>, + start: (usize, usize), +} + +impl Puzzle { + pub fn new(input: &str) -> Self { + let mut map: Vec> = Vec::new(); + let mut start: (usize, usize) = (0, 0); + + input.lines() + .filter(|l| !l.is_empty()) + .enumerate() + .for_each(|(i, l)| { + let mut c: Vec = Vec::new(); + + c.push(' '); + c.append(&mut l.chars().collect::>()); + c.push(' '); + + match c.iter().position(|&a| a == 'S') { + Some(p) => start = (i + 1, p), + None => {}, + } + + + if i == 0 { + map.push(vec![' '; c.len()]); + } + map.push(c); + + }); + + map.push(vec![' '; map[0].len()]); + + let seen_at_step: Vec> = vec![ + vec![0 ; map[0].len()] + ; + map.len() + ]; + + Self { + map, + seen_at_step, + start, + } + } + + // une fois visitées les cases clignotes + // '.' -> 'O' -> '.' -> 'O' + pub fn travel(&mut self, end_step: u32) -> u32 { + let mut queue: VecDeque<(usize, usize)> = VecDeque::new(); + queue.push_back(self.start); + + let mut step: u32 = 1; + + while step <= end_step { + let mut queue_next: VecDeque<(usize, usize)> = VecDeque::new(); + while let Some(q) = queue.pop_front() { + let neighbours = [ + (q.0, q.1 - 1), + (q.0, q.1 + 1), + (q.0 - 1, q.1), + (q.0 + 1, q.1), + ]; + for n in neighbours { + if self.can_travel_to(n) { + self.seen_at_step[n.0][n.1] = step; + queue_next.push_back(n); + } + } + } + + step += 1; + queue = queue_next.clone(); + } + + self.seen_at_step.iter() + .map(|r| { + r.iter().filter(|&&s| { + s > 0 && s % 2 == end_step % 2 + }) + .count() + }) + .sum::() as u32 + } + + fn can_travel_to(&self, n: (usize, usize)) -> bool { + self.seen_at_step[n.0][n.1] == 0 && ['.', 'S'].contains(&self.map[n.0][n.1]) + } +} + +fn run_part1(input: &str, end_step: u32) -> Result> { + println!("Running day21 - part 1"); + + let mut puzzle = Puzzle::new(input); + //println!("{:?}", puzzle); + let res = puzzle.travel(end_step); + Ok(res) +} + +fn run_part2(input: &str) -> Result> { + println!("Running day21 - part 2"); + let res = 0; + Ok(res) +} + +#[cfg(test)] +mod tests { + use super::*; + + static TEXT_INPUT: &str = "\ +........... +.....###.#. +.###.##..#. +..#.#...#.. +....#.#.... +.##..S####. +.##..#...#. +.......##.. +.##.#.####. +.##..##.##. +..........."; + + #[test] + fn day21_part1() { + // N = 6 + let res = run_part1(TEXT_INPUT, 6); + assert_eq!(16, res.unwrap()); + } + + #[test] + fn day21_part2() { + let res = run_part2(TEXT_INPUT); + assert_eq!(0, res.unwrap()); + } +} diff --git a/src/main.rs b/src/main.rs index e15fe5b..34d88df 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,7 @@ pub mod day16; pub mod day18; pub mod day19; pub mod day20; +pub mod day21; fn main() { let args: Vec = env::args().collect(); @@ -55,6 +56,7 @@ fn run(day: &str, input_file: &str) -> Result<(), Box> { "day18" => day18::run(input_file)?, "day19" => day19::run(input_file)?, "day20" => day20::run(input_file)?, + "day21" => day21::run(input_file)?, _ => return Err(format!("unknown day \"{day}\"").into()), } Ok(())