Multi Path

This commit is contained in:
hal8174 2023-12-10 14:09:30 +01:00
parent 6f6a7f978b
commit c10843ad2f
3 changed files with 142 additions and 34 deletions

View file

@ -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
View 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}");
}

View file

@ -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;
}
}
}
}