diff --git a/input/day20_example2.txt b/input/day20_example2.txt new file mode 100644 index 0000000..af833a1 --- /dev/null +++ b/input/day20_example2.txt @@ -0,0 +1,37 @@ + Z L X W C + Z P Q B K + ###########.#.#.#.#######.############### + #...#.......#.#.......#.#.......#.#.#...# + ###.#.#.#.#.#.#.#.###.#.#.#######.#.#.### + #.#...#.#.#...#.#.#...#...#...#.#.......# + #.###.#######.###.###.#.###.###.#.####### + #...#.......#.#...#...#.............#...# + #.#########.#######.#.#######.#######.### + #...#.# F R I Z #.#.#.# + #.###.# D E C H #.#.#.# + #.#...# #...#.# + #.###.# #.###.# + #.#....OA WB..#.#..ZH + #.###.# #.#.#.# +CJ......# #.....# + ####### ####### + #.#....CK #......IC + #.###.# #.###.# + #.....# #...#.# + ###.### #.#.#.# +XF....#.# RF..#.#.# + #####.# ####### + #......CJ NM..#...# + ###.#.# #.###.# +RE....#.# #......RF + ###.### X X L #.#.#.# + #.....# F Q P #.#.#.# + ###.###########.###.#######.#########.### + #.....#...#.....#.......#...#.....#.#...# + #####.#.###.#######.#######.###.###.#.#.# + #.......#.......#.#.#.#.#...#...#...#.#.# + #####.###.#####.#.#.#.#.###.###.#.###.### + #.......#.....#.#...#...............#...# + #############.#.#.###.################### + A O F N + A A D M \ No newline at end of file diff --git a/src/tasks/day20.rs b/src/tasks/day20.rs index c9f2060..b548de7 100644 --- a/src/tasks/day20.rs +++ b/src/tasks/day20.rs @@ -5,6 +5,10 @@ pub fn run() { let maze = Maze::from(&input, PortalField::curried_factory); let part1 = maze.shortest_path(); println!("Part 1: {}", part1); + + let maze = Maze::from(&input, DimensionField::curried_factory); + let part1 = maze.shortest_path(); + println!("Part 2: {}", part1); } type C = i32; @@ -94,17 +98,24 @@ struct DimensionField { } impl DimensionField { - fn is_inner(&self) -> bool { - !self.is_outer() - } - fn is_outer(&self) -> bool { - false + fn is_inward(&self) -> bool { + let p = self.point; + p.x > 2 && p.x < self.map_width - 3 && p.y > 2 && p.y < self.map_height - 3 } } impl Field for DimensionField { fn neighbors(&self, at_level: usize) -> Vec { - todo!() + let mut result: Vec = self.neighbors.iter().map(|n| RealPoint::from(*n, at_level)).collect(); + if let Some(destination) = self.jump { + if self.is_inward() { + result.push(RealPoint::from(destination, at_level + 1)); + } else if at_level > 0 { + result.push(RealPoint::from(destination, at_level - 1)); + } + } + + result } fn set_label_partner(&mut self, point: MapPoint) { @@ -266,8 +277,10 @@ fn bfs(map: &FieldMap, start: RealPoint, finish: RealPoint) -> usize { let mut seen: HashSet = HashSet::new(); open.push_back((start, 0)); + seen.insert(start); while let Some((p, d)) = open.pop_front() { + println!("{:?} {}", p, d); if p == finish { return d; } @@ -275,24 +288,32 @@ fn bfs(map: &FieldMap, start: RealPoint, finish: RealPoint) -> usize { for neighbor in map[&p.map_point()].neighbors(p.level) { if !seen.contains(&neighbor) { open.push_back((neighbor, d + 1)); + seen.insert(neighbor); } - seen.insert(neighbor); } } panic!("no path found") + PortalField } #[cfg(test)] mod test { - use crate::tasks::day20::{Field, Maze, PortalField}; + use crate::tasks::day20::{DimensionField, Field, Maze, PortalField}; #[test] - fn example1() { + fn example_part1() { let input = std::fs::read_to_string("input/day20_example1.txt").unwrap(); let maze = Maze::from(&input, PortalField::curried_factory); assert_eq!(maze.shortest_path(), 23); } + #[test] + fn example_part2() { + let input = std::fs::read_to_string("input/day20_example2.txt").unwrap(); + let maze = Maze::from(&input, DimensionField::curried_factory); + assert_eq!(maze.shortest_path(), 396); + } + #[test] fn result() { let input = std::fs::read_to_string("input/day20.txt").unwrap();