day20 refactored for part 2 - currying

This commit is contained in:
2022-10-02 16:53:55 +02:00
parent 922f2a483c
commit 3b829649f3

View File

@@ -2,13 +2,13 @@ use std::collections::{HashMap, HashSet, VecDeque};
pub fn run() {
let input = std::fs::read_to_string("input/day20.txt").unwrap();
let maze = Maze::from(&input, PortalField::create);
let maze = Maze::from(&input, PortalField::curried_factory);
let part1 = maze.shortest_path();
println!("Part 1: {}", part1);
}
type C = i32;
type FieldFactory = fn(&MapPoint) -> Box<dyn Field>;
type FieldFactory = Box<dyn Fn(&MapPoint) -> Box<dyn Field>>;
#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug)]
struct MapPoint {
@@ -54,7 +54,7 @@ trait Field {
fn neighbors(&self, at_level: usize) -> Vec<RealPoint>;
fn set_label_partner(&mut self, point: MapPoint);
fn set_neighbors(&mut self, neighbors: Vec<MapPoint>);
fn create(point: &MapPoint) -> Box<dyn Field> where Self: Sized;
fn curried_factory(width: C, height: C) -> FieldFactory where Self: Sized;
}
struct PortalField {
@@ -80,26 +80,45 @@ impl Field for PortalField {
self.neighbors = neighbors;
}
fn create(_: &MapPoint) -> Box<dyn Field> where Self: Sized {
Box::new(PortalField::new())
fn curried_factory(_: C, _: C) -> FieldFactory {
Box::new(|_| Box::new(PortalField::new()))
}
}
//impl Field for PortalField {
// fn neighbors(self, level: usize) -> Vec<Point> {
// if let Some((direction, p)) = self.dimension_neighbor {
// if direction == DimensionUp && level < 0 {
// let mut v = self.neighbors.clone();
// v.push(p);
// v
// } else {
// self.neighbors.clone()
// }
// } else {
// self.neighbors.clone()
// }
// }
//}
struct DimensionField {
point: MapPoint,
neighbors: Vec<MapPoint>,
jump: Option<MapPoint>,
map_width: C,
map_height: C,
}
impl DimensionField {
fn is_inner(&self) -> bool {
!self.is_outer()
}
fn is_outer(&self) -> bool {
false
}
}
impl Field for DimensionField {
fn neighbors(&self, at_level: usize) -> Vec<RealPoint> {
todo!()
}
fn set_label_partner(&mut self, point: MapPoint) {
self.jump = Some(point);
}
fn set_neighbors(&mut self, neighbors: Vec<MapPoint>) {
self.neighbors = neighbors;
}
fn curried_factory(width: C, height: C) -> FieldFactory {
Box::new(move |point: &MapPoint| Box::new(Self { point: *point, neighbors: vec![], jump: None, map_width: width, map_height: height }))
}
}
type FieldMap = HashMap<MapPoint, Box<dyn Field>>;
@@ -110,10 +129,10 @@ struct Maze {
}
impl Maze {
fn from(input: &String, field_factory: FieldFactory) -> Self {
fn from(input: &String, factory: fn(C, C) -> FieldFactory) -> Self {
let (moc, width, height) = Self::map_of_chars(input);
let mut map = Self::create_map_of_free_spots(&moc, field_factory);
let mut map = Self::create_map_of_free_spots(&moc, factory(width, height));
Self::add_physical_neighbors(&mut map);
let labels = Self::labels(&moc, width, height);
Self::process_labels(&mut map, &labels);
@@ -270,14 +289,14 @@ mod test {
#[test]
fn example1() {
let input = std::fs::read_to_string("input/day20_example1.txt").unwrap();
let maze = Maze::from(&input, PortalField::create);
let maze = Maze::from(&input, PortalField::curried_factory);
assert_eq!(maze.shortest_path(), 23);
}
#[test]
fn result() {
let input = std::fs::read_to_string("input/day20.txt").unwrap();
let maze = Maze::from(&input, PortalField::create);
let maze = Maze::from(&input, PortalField::curried_factory);
assert_eq!(maze.shortest_path(), 454);
}
}