diff --git a/data/examples/18.txt b/data/examples/18.txt new file mode 100644 index 000000000..79c8583 --- /dev/null +++ b/data/examples/18.txt @@ -0,0 +1,25 @@ +5,4 +4,2 +4,5 +3,0 +2,1 +6,3 +2,4 +1,5 +0,6 +3,3 +2,6 +5,1 +1,2 +5,5 +2,5 +6,5 +1,4 +0,4 +6,4 +1,1 +6,1 +1,0 +0,5 +1,6 +2,0 diff --git a/src/bin/18.rs b/src/bin/18.rs new file mode 100644 index 000000000..cb9ab9c --- /dev/null +++ b/src/bin/18.rs @@ -0,0 +1,94 @@ +use std::collections::VecDeque; + +use hashbrown::{HashMap, HashSet}; +use itertools::Itertools; + +use aoc::{ + grid_vec::{Direction, Point}, + pnt, +}; + +fn parse_input(input: &str) -> Vec { + input + .lines() + .map(|x| { + x.split(',') + .filter_map(|y| y.parse().ok()) + .collect_tuple() + .unwrap() + }) + .map(|x: (usize, usize)| Point { i: x.1, j: x.0 }) + .collect_vec() +} + +fn bfs( + visited: &mut HashMap, + queue: &mut VecDeque<(Point, usize)>, + corruption: &HashSet, + end: Point, +) -> Option { + visited.clear(); + queue.clear(); + + queue.push_back((pnt!(0, 0), 0)); + + while let Some((p, l)) = queue.pop_front() { + if visited.contains_key(&p) { + continue; + } + visited.insert(p, l); + + if p == end { + break; + } + + for d in Direction::CROSS { + let n = p + d; + + let in_bounds = n.bounded_by(&end); + let not_visited = !visited.contains_key(&n); + let not_corrupted = !corruption.contains(&n); + + if in_bounds && not_visited && not_corrupted { + queue.push_back((n, l + 1)); + } + } + } + + visited.get(&end).copied() +} + +pub fn part_one(input: &str) -> Option { + let falling_bytes = parse_input(input); + + let mut visited = HashMap::new(); + let mut queue = VecDeque::new(); + + let end = pnt!(70, 70); + let corruption = HashSet::from_iter(falling_bytes.iter().copied().take(1024)); + + bfs(&mut visited, &mut queue, &corruption, end) +} + +pub fn part_two(input: &str) -> Option { + let falling_bytes = parse_input(input); + + let mut visited = HashMap::new(); + let mut queue = VecDeque::new(); + + let end = pnt!(70, 70); + let mut corruption = HashSet::new(); + let mut c = 0; + + while bfs(&mut visited, &mut queue, &corruption, end).is_some() { + corruption.insert(falling_bytes[c]); + c += 1; + } + + let fb = falling_bytes[c - 1]; + + Some(format!("{},{}", fb.j, fb.i)) +} + +aoc::solution!(18); +