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