Refactor bruteforce interface

This commit is contained in:
hal8174 2023-12-11 20:23:32 +01:00
parent 2bc323aa58
commit 20073b88ce
2 changed files with 76 additions and 45 deletions

View file

@ -1,39 +1,24 @@
use factorio_blueprint::{ use factorio_blueprint::{
belt_finding::{ belt_finding::{
brute_force::{Bruteforce, PathField}, brute_force::{Bruteforce, BruteforceBuilder, PathField},
Direction, Position, Direction, Position,
}, },
misc::Map, misc::Map,
}; };
fn main() { fn main() {
let mut b = Bruteforce { let mut b = BruteforceBuilder::new(6, 8);
map: Map::new(5, 10),
path: vec![],
end_pos: Position::new(4, 9),
end_dir: Direction::Up,
count: 0,
solution_count: 0,
};
b.apply_path_field(PathField::Belt { b.add_path(
pos: Position::new(1, 0), (Position::new(1, 0), Direction::Down),
dir: Direction::Down, (Position::new(4, 6), Direction::Up),
}); );
b.map.get_mut(0, 2).blocked = true; b.set_blocked_range(0, 2, 5, 5, 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.map.get_mut(0, 4).blocked = true; let mut b = b.build();
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;
while b.next_finish_state() { while b.next_finish_state() {
println!("{}\n{}\n{}", b.count, b.solution_count, b); println!("{}\n{}\n{}", b.count(), b.solution_count(), b);
} }
} }

View file

@ -50,15 +50,63 @@ impl PathField {
} }
} }
static MAX_UNDERGROUND_LENGTH: u8 = 5; static MAX_UNDERGROUND_LENGTH: u8 = 6;
pub struct BruteforceBuilder {
map: Map<BruteforceField>,
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 struct Bruteforce {
pub map: Map<BruteforceField>, map: Map<BruteforceField>,
pub path: Vec<PathField>, path: Vec<PathField>,
pub end_pos: Position, end: (Position, Direction),
pub end_dir: Direction, solution_count: u128,
pub solution_count: u128, count: u128,
pub count: u128,
} }
impl Bruteforce { impl Bruteforce {
@ -113,27 +161,15 @@ impl Bruteforce {
match self.path.last().unwrap() { match self.path.last().unwrap() {
PathField::Belt { pos, dir } => self PathField::Belt { pos, dir } => self
.pos_in_direction(pos, dir, 1) .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(), .is_some(),
PathField::Underground { pos, dir, len } => self PathField::Underground { pos, dir, len } => self
.pos_in_direction(pos, dir, *len as usize + 1) .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(), .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) { fn path_field_end(&self, path_field: &PathField) -> (Position, Direction) {
match path_field { match path_field {
PathField::Belt { pos, dir } => (*pos, *dir), 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)), 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 { 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 // Print body
for y in 0..self.map.height { for y in 0..self.map.height {