diff options
Diffstat (limited to 'aoc/2024/06/rust/src/main.rs')
| -rw-r--r-- | aoc/2024/06/rust/src/main.rs | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/aoc/2024/06/rust/src/main.rs b/aoc/2024/06/rust/src/main.rs new file mode 100644 index 0000000..ca78bcd --- /dev/null +++ b/aoc/2024/06/rust/src/main.rs @@ -0,0 +1,105 @@ +use std::collections::HashSet; +use std::{collections::HashMap, io}; + +#[derive(Clone)] +enum Cell { + Empty, + Obstacle, +} + +#[derive(Clone)] +enum Direction { + L = 0b1, + R = 0b10, + U = 0b100, + D = 0b1000, +} + +impl Direction { + fn shift(&self, point: (isize, isize)) -> (isize, isize) { + let (x, y) = point; + match self { + Direction::L => (x - 1, y), + Direction::R => (x + 1, y), + Direction::U => (x, y - 1), + Direction::D => (x, y + 1), + } + } + + fn rotate(&self) -> Self { + use Direction::*; + match self { + L => U, + R => D, + U => R, + D => L, + } + } +} + +fn main() -> io::Result<()> { + let mut map = HashMap::new(); + let mut start = None; + io::stdin() + .lines() + .flatten() + .enumerate() + .flat_map(|(y, line)| { + line.chars() + .enumerate() + .map(|(x, ch)| ([x as isize, y as isize], ch)) + .collect::<Vec<_>>() + }) + .for_each(|([x, y], ch)| match ch { + '.' => { + map.insert((x, y), Cell::Empty); + } + '^' => { + map.insert((x, y), Cell::Empty); + start = Some((x, y)) + } + '#' => { + map.insert((x, y), Cell::Obstacle); + } + _ => panic!(), + }); + let start = start.unwrap(); + + let visited = path_len(&map, start.clone()).unwrap(); + let silver: usize = visited.len(); + let gold: usize = visited + .iter() + .filter(|&p| { + let mut map = map.clone(); + map.insert(*p, Cell::Obstacle); + path_len(&map, start.clone()).is_none() + }) + .count(); + println!("silver: {silver}"); + println!("gold: {gold}"); + + return Ok(()); +} + +fn path_len( + map: &HashMap<(isize, isize), Cell>, + mut pos: (isize, isize), +) -> Option<HashSet<(isize, isize)>> { + let mut visited = HashMap::new(); + let mut dir = Direction::U; + + loop { + let before = visited.entry(pos).or_insert(0 as u8); + if *before & dir.clone() as u8 > 0 { + return None; + } + *before |= dir.clone() as u8; + + let ahead = dir.shift(pos); + match map.get(&ahead) { + Some(Cell::Empty) => pos = ahead, + Some(Cell::Obstacle) => dir = dir.rotate(), + None => return Some(visited.into_keys().collect()), + }; + } +} |
