Multi Path
This commit is contained in:
parent
6f6a7f978b
commit
c10843ad2f
3 changed files with 142 additions and 34 deletions
|
|
@ -1,7 +1,7 @@
|
|||
use factorio_blueprint::belt_finding::{Position, Problem};
|
||||
|
||||
fn main() {
|
||||
let mut p = Problem::new(17, 13, Position::new(3, 8), Position::new(13, 5));
|
||||
let mut p = Problem::new(17, 13);
|
||||
|
||||
p.set_blocked(0, 3, true);
|
||||
|
||||
|
|
@ -31,9 +31,27 @@ fn main() {
|
|||
|
||||
p.set_blocked(16, 9, true);
|
||||
|
||||
p.add_connection(Position::new(3, 7), Position::new(13, 4));
|
||||
p.add_connection(Position::new(3, 8), Position::new(13, 5));
|
||||
|
||||
p.add_connection(Position::new(3, 4), Position::new(13, 8));
|
||||
p.add_connection(Position::new(3, 5), Position::new(13, 7));
|
||||
|
||||
// p.set_blocked(8, 12, true);
|
||||
// p.set_blocked(8, 11, true);
|
||||
// p.set_blocked(8, 10, true);
|
||||
// p.set_blocked(8, 9, true);
|
||||
// p.set_blocked(8, 8, true);
|
||||
// p.set_blocked(8, 7, true);
|
||||
// p.set_blocked(8, 6, true);
|
||||
// p.set_blocked(8, 5, true);
|
||||
// p.set_blocked(8, 4, true);
|
||||
// p.set_blocked(8, 3, true);
|
||||
// p.set_blocked(8, 2, true);
|
||||
// p.set_blocked(8, 1, true);
|
||||
// p.set_blocked(8, 0, true);
|
||||
|
||||
println!("{}", p);
|
||||
|
||||
p.find_path();
|
||||
|
||||
println!("{}", p);
|
||||
}
|
||||
|
|
|
|||
32
examples/solve_belt2.rs
Normal file
32
examples/solve_belt2.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use factorio_blueprint::belt_finding::{Position, Problem};
|
||||
|
||||
fn main() {
|
||||
let mut p = Problem::new(33, 13);
|
||||
|
||||
p.set_blocked_range(1, 3, 2, 5, true);
|
||||
p.set_blocked_range(1, 7, 2, 9, true);
|
||||
|
||||
p.set_blocked(0, 3, true);
|
||||
p.set_blocked(0, 8, true);
|
||||
|
||||
p.set_blocked_range(10, 0, 21, 2, true);
|
||||
p.set_blocked_range(10, 5, 21, 7, true);
|
||||
p.set_blocked_range(10, 10, 21, 12, true);
|
||||
|
||||
p.set_blocked_range(30, 3, 31, 5, true);
|
||||
p.set_blocked_range(30, 7, 31, 9, true);
|
||||
p.set_blocked(32, 3, true);
|
||||
p.set_blocked(32, 9, true);
|
||||
|
||||
p.add_connection(Position::new(3, 3), Position::new(29, 7));
|
||||
p.add_connection(Position::new(3, 4), Position::new(29, 9));
|
||||
p.add_connection(Position::new(3, 5), Position::new(29, 8));
|
||||
|
||||
p.add_connection(Position::new(3, 7), Position::new(29, 3));
|
||||
p.add_connection(Position::new(3, 8), Position::new(29, 5));
|
||||
p.add_connection(Position::new(3, 9), Position::new(29, 4));
|
||||
|
||||
println!("{p}");
|
||||
p.find_path();
|
||||
println!("{p}");
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ use crate::graph::wheighted_graph::shortest_path::dijkstra;
|
|||
use crate::graph::wheighted_graph::WheightedGraph;
|
||||
use crate::priority_queue::BinaryHeap;
|
||||
use crate::{misc::Map, priority_queue::PriorityQueue};
|
||||
use colored::Colorize;
|
||||
use colored::{Color, Colorize};
|
||||
use std::fmt::{write, Display};
|
||||
use std::io::Write;
|
||||
|
||||
|
|
@ -28,30 +28,84 @@ impl Position {
|
|||
#[derive(Default, Clone, Copy)]
|
||||
pub struct Field {
|
||||
pub blocked: bool,
|
||||
wheight: f64,
|
||||
}
|
||||
|
||||
pub struct Problem {
|
||||
map: Map<Field>,
|
||||
start: Position,
|
||||
end: Position,
|
||||
path: Vec<Position>,
|
||||
start: Vec<Position>,
|
||||
end: Vec<Position>,
|
||||
path: Vec<Vec<Position>>,
|
||||
}
|
||||
|
||||
impl Problem {
|
||||
pub fn new(width: usize, height: usize, start: Position, end: Position) -> Self {
|
||||
pub fn new(width: usize, height: usize) -> Self {
|
||||
Self {
|
||||
map: Map::new(width, height),
|
||||
start,
|
||||
end,
|
||||
start: Vec::new(),
|
||||
end: Vec::new(),
|
||||
path: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_connection(&mut self, start: Position, end: Position) {
|
||||
self.start.push(start);
|
||||
self.end.push(end);
|
||||
self.path.push(Vec::new());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_wheights(&mut self, without: usize) {
|
||||
for x in 0..self.map.width {
|
||||
for y in 0..self.map.height {
|
||||
let mut wheight = 1.0;
|
||||
|
||||
if self.map.get(x, y).blocked {
|
||||
wheight += 100.0;
|
||||
}
|
||||
|
||||
self.map.get_mut(x, y).wheight = wheight;
|
||||
}
|
||||
}
|
||||
|
||||
for (i, path) in self.path.iter().enumerate() {
|
||||
if i != without {
|
||||
for p in path {
|
||||
self.map.get_mut(p.x, p.y).wheight += 50.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for p in &self.start {
|
||||
self.map.get_mut(p.x, p.y).wheight += 200.0;
|
||||
}
|
||||
|
||||
for p in &self.end {
|
||||
self.map.get_mut(p.x, p.y).wheight += 200.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static COLORS: [Color; 6] = [
|
||||
Color::Red,
|
||||
Color::Green,
|
||||
Color::Yellow,
|
||||
Color::Blue,
|
||||
Color::Magenta,
|
||||
Color::Cyan,
|
||||
];
|
||||
|
||||
impl Display for Problem {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let width_digits = self.map.width.ilog10() + 1;
|
||||
|
|
@ -83,22 +137,28 @@ impl Display for Problem {
|
|||
write!(f, "{:1$}", y, height_digits as usize)?;
|
||||
|
||||
for x in 0..self.map.width {
|
||||
if self.start == Position::new(x, y) {
|
||||
write!(f, "{}", "s".blue())?;
|
||||
} else if self.end == Position::new(x, y) {
|
||||
write!(f, "{}", "t".blue())?;
|
||||
} else if let Some(p) = self.path.iter().position(|p| p == &Position::new(x, y)) {
|
||||
if self.path[p].x < self.path[p + 1].x {
|
||||
write!(f, "{}", "→".blue())?;
|
||||
} else if self.path[p].x > self.path[p + 1].x {
|
||||
write!(f, "{}", "←".blue())?;
|
||||
} else if self.path[p].y < self.path[p + 1].y {
|
||||
write!(f, "{}", "↓".blue())?;
|
||||
} else if self.path[p].y > self.path[p + 1].y {
|
||||
write!(f, "{}", "↑".blue())?;
|
||||
if let Some(i) = self.start.iter().position(|p| p == &Position::new(x, y)) {
|
||||
write!(f, "{}", "s".color(COLORS[i]))?;
|
||||
} else if let Some(i) = self.end.iter().position(|p| p == &Position::new(x, y)) {
|
||||
write!(f, "{}", "t".color(COLORS[i]))?;
|
||||
} else if let Some((i, p)) = self.path.iter().enumerate().find_map(|(i, v)| {
|
||||
v.iter()
|
||||
.position(|p| p == &Position::new(x, y))
|
||||
.map(|j| (i, j))
|
||||
}) {
|
||||
if self.path[i][p].x < self.path[i][p + 1].x {
|
||||
write!(f, "{}", "→".color(COLORS[i]))?;
|
||||
} else if self.path[i][p].x > self.path[i][p + 1].x {
|
||||
write!(f, "{}", "←".color(COLORS[i]))?;
|
||||
} else if self.path[i][p].y < self.path[i][p + 1].y {
|
||||
write!(f, "{}", "↓".color(COLORS[i]))?;
|
||||
} else if self.path[i][p].y > self.path[i][p + 1].y {
|
||||
write!(f, "{}", "↑".color(COLORS[i]))?;
|
||||
}
|
||||
} else if self.map.get(x, y).blocked {
|
||||
write!(f, "{}", "#")?;
|
||||
} else if x % 8 == 0 || y % 8 == 0 {
|
||||
write!(f, "∙")?;
|
||||
} else {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
|
|
@ -143,10 +203,7 @@ impl<'a> WheightedGraph for MapInternal<'a> {
|
|||
} else {
|
||||
let t = self.get_direction(*node);
|
||||
|
||||
let v = t
|
||||
.iter()
|
||||
.flatten()
|
||||
.filter_map(|&p| (!self.map.get(p.x, p.y).blocked).then_some(p));
|
||||
let v = t.iter().flatten();
|
||||
|
||||
v.count()
|
||||
}
|
||||
|
|
@ -157,20 +214,21 @@ impl<'a> WheightedGraph for MapInternal<'a> {
|
|||
|
||||
t.iter()
|
||||
.flatten()
|
||||
.filter_map(|&p| (!self.map.get(p.x, p.y).blocked).then_some(p))
|
||||
.nth(num)
|
||||
.map(|p| (p, 1.0))
|
||||
.map(|&p| (p, self.map.get(p.x, p.y).wheight))
|
||||
}
|
||||
}
|
||||
|
||||
impl Problem {
|
||||
pub fn find_path(&mut self) {
|
||||
let m = MapInternal { map: &self.map };
|
||||
for i in 0..self.start.len() {
|
||||
self.calculate_wheights(i);
|
||||
let m = MapInternal { map: &self.map };
|
||||
let p = dijkstra::<MapInternal, BinaryHeap<_>>(&m, self.start[i], self.end[i]);
|
||||
|
||||
let p = dijkstra::<MapInternal, BinaryHeap<_>>(&m, self.start, self.end);
|
||||
|
||||
if let Some(p) = p {
|
||||
self.path = p;
|
||||
if let Some(p) = p {
|
||||
self.path[i] = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue