From 20073b88ce737d9bfa7b0192c55a3f05dad4e85a Mon Sep 17 00:00:00 2001 From: hal8174 Date: Mon, 11 Dec 2023 20:23:32 +0100 Subject: [PATCH] Refactor bruteforce interface --- examples/brute_force.rs | 33 ++++--------- src/belt_finding/brute_force.rs | 88 +++++++++++++++++++++++++-------- 2 files changed, 76 insertions(+), 45 deletions(-) diff --git a/examples/brute_force.rs b/examples/brute_force.rs index 6ff9db5..b78fdfa 100644 --- a/examples/brute_force.rs +++ b/examples/brute_force.rs @@ -1,39 +1,24 @@ use factorio_blueprint::{ belt_finding::{ - brute_force::{Bruteforce, PathField}, + brute_force::{Bruteforce, BruteforceBuilder, PathField}, Direction, Position, }, misc::Map, }; fn main() { - let mut b = Bruteforce { - map: Map::new(5, 10), - path: vec![], - end_pos: Position::new(4, 9), - end_dir: Direction::Up, - count: 0, - solution_count: 0, - }; + let mut b = BruteforceBuilder::new(6, 8); - b.apply_path_field(PathField::Belt { - pos: Position::new(1, 0), - dir: Direction::Down, - }); + b.add_path( + (Position::new(1, 0), Direction::Down), + (Position::new(4, 6), Direction::Up), + ); - b.map.get_mut(0, 2).blocked = true; - b.map.get_mut(1, 2).blocked = true; - b.map.get_mut(2, 2).blocked = true; - b.map.get_mut(3, 2).blocked = true; - b.map.get_mut(4, 2).blocked = true; + b.set_blocked_range(0, 2, 5, 5, true); - b.map.get_mut(0, 4).blocked = true; - b.map.get_mut(1, 4).blocked = true; - b.map.get_mut(2, 4).blocked = true; - b.map.get_mut(3, 4).blocked = true; - b.map.get_mut(4, 4).blocked = true; + let mut b = b.build(); while b.next_finish_state() { - println!("{}\n{}\n{}", b.count, b.solution_count, b); + println!("{}\n{}\n{}", b.count(), b.solution_count(), b); } } diff --git a/src/belt_finding/brute_force.rs b/src/belt_finding/brute_force.rs index 70b8a7a..ff82a6f 100644 --- a/src/belt_finding/brute_force.rs +++ b/src/belt_finding/brute_force.rs @@ -50,15 +50,63 @@ impl PathField { } } -static MAX_UNDERGROUND_LENGTH: u8 = 5; +static MAX_UNDERGROUND_LENGTH: u8 = 6; + +pub struct BruteforceBuilder { + map: Map, + path: Vec<[(Position, Direction); 2]>, +} + +impl BruteforceBuilder { + pub fn new(width: usize, height: usize) -> Self { + Self { + map: Map::new(width, height), + path: Vec::new(), + } + } + + pub fn add_path(&mut self, start: (Position, Direction), end: (Position, Direction)) { + self.path.push([start, end]); + } + + pub fn set_blocked(&mut self, x: usize, y: usize, blocked: bool) { + self.map.get_mut(x, y).blocked = blocked; + } + + pub fn set_blocked_range(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, blocked: bool) { + for x in x1..=x2 { + for y in y1..=y2 { + self.set_blocked(x, y, blocked); + } + } + } + + pub fn build(self) -> Bruteforce { + let mut b = Bruteforce { + map: self.map, + path: Vec::new(), + end: self.path[0][1], + solution_count: 0, + count: 0, + }; + + b.apply_path_field(PathField::Belt { + pos: self.path[0][0].0, + dir: self.path[0][0].1, + }); + + b.map.get_mut(self.path[0][1].0.x, self.path[0][1].0.y); + + b + } +} pub struct Bruteforce { - pub map: Map, - pub path: Vec, - pub end_pos: Position, - pub end_dir: Direction, - pub solution_count: u128, - pub count: u128, + map: Map, + path: Vec, + end: (Position, Direction), + solution_count: u128, + count: u128, } impl Bruteforce { @@ -113,27 +161,15 @@ impl Bruteforce { match self.path.last().unwrap() { PathField::Belt { pos, dir } => self .pos_in_direction(pos, dir, 1) - .filter(|p| p == &self.end_pos && dir != &self.end_dir.reverse()) + .filter(|p| p == &self.end.0 && dir != &self.end.1.reverse()) .is_some(), PathField::Underground { pos, dir, len } => self .pos_in_direction(pos, dir, *len as usize + 1) - .filter(|p| p == &self.end_pos && dir != &self.end_dir.reverse()) + .filter(|p| p == &self.end.0 && dir != &self.end.1.reverse()) .is_some(), } } - fn next_state_internal(&mut self, pos: Position, dir: Direction) -> bool { - if let Some(next_pos) = self - .pos_in_direction(&pos, &dir, 1) - .filter(|p| !self.map.get(p.x, p.y).blocked) - { - self.apply_path_field(PathField::Belt { pos: next_pos, dir }); - true - } else { - false - } - } - fn path_field_end(&self, path_field: &PathField) -> (Position, Direction) { match path_field { PathField::Belt { pos, dir } => (*pos, *dir), @@ -246,6 +282,14 @@ impl Bruteforce { Direction::Left => pos.x.checked_sub(len).map(|x| Position::new(x, pos.y)), } } + + pub fn count(&self) -> u128 { + self.count + } + + pub fn solution_count(&self) -> u128 { + self.solution_count + } } impl Display for Bruteforce { @@ -301,6 +345,8 @@ impl Display for Bruteforce { } } + m.set(self.end.0.x, self.end.0.y, Some((0, "t"))); + // Print body for y in 0..self.map.height {