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}; use factorio_blueprint::belt_finding::{Position, Problem};
fn main() { 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); p.set_blocked(0, 3, true);
@ -31,9 +31,27 @@ fn main() {
p.set_blocked(16, 9, true); 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); println!("{}", p);
p.find_path(); p.find_path();
println!("{}", p); 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::graph::wheighted_graph::WheightedGraph;
use crate::priority_queue::BinaryHeap; use crate::priority_queue::BinaryHeap;
use crate::{misc::Map, priority_queue::PriorityQueue}; use crate::{misc::Map, priority_queue::PriorityQueue};
use colored::Colorize; use colored::{Color, Colorize};
use std::fmt::{write, Display}; use std::fmt::{write, Display};
use std::io::Write; use std::io::Write;
@ -28,30 +28,84 @@ impl Position {
#[derive(Default, Clone, Copy)] #[derive(Default, Clone, Copy)]
pub struct Field { pub struct Field {
pub blocked: bool, pub blocked: bool,
wheight: f64,
} }
pub struct Problem { pub struct Problem {
map: Map<Field>, map: Map<Field>,
start: Position, start: Vec<Position>,
end: Position, end: Vec<Position>,
path: Vec<Position>, path: Vec<Vec<Position>>,
} }
impl Problem { impl Problem {
pub fn new(width: usize, height: usize, start: Position, end: Position) -> Self { pub fn new(width: usize, height: usize) -> Self {
Self { Self {
map: Map::new(width, height), map: Map::new(width, height),
start, start: Vec::new(),
end, end: Vec::new(),
path: 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) { pub fn set_blocked(&mut self, x: usize, y: usize, blocked: bool) {
self.map.get_mut(x, y).blocked = blocked; 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 { impl Display for Problem {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let width_digits = self.map.width.ilog10() + 1; let width_digits = self.map.width.ilog10() + 1;
@ -83,22 +137,28 @@ impl Display for Problem {
write!(f, "{:1$}", y, height_digits as usize)?; write!(f, "{:1$}", y, height_digits as usize)?;
for x in 0..self.map.width { for x in 0..self.map.width {
if self.start == Position::new(x, y) { if let Some(i) = self.start.iter().position(|p| p == &Position::new(x, y)) {
write!(f, "{}", "s".blue())?; write!(f, "{}", "s".color(COLORS[i]))?;
} else if self.end == Position::new(x, y) { } else if let Some(i) = self.end.iter().position(|p| p == &Position::new(x, y)) {
write!(f, "{}", "t".blue())?; write!(f, "{}", "t".color(COLORS[i]))?;
} else if let Some(p) = self.path.iter().position(|p| p == &Position::new(x, y)) { } else if let Some((i, p)) = self.path.iter().enumerate().find_map(|(i, v)| {
if self.path[p].x < self.path[p + 1].x { v.iter()
write!(f, "{}", "".blue())?; .position(|p| p == &Position::new(x, y))
} else if self.path[p].x > self.path[p + 1].x { .map(|j| (i, j))
write!(f, "{}", "".blue())?; }) {
} else if self.path[p].y < self.path[p + 1].y { if self.path[i][p].x < self.path[i][p + 1].x {
write!(f, "{}", "".blue())?; write!(f, "{}", "".color(COLORS[i]))?;
} else if self.path[p].y > self.path[p + 1].y { } else if self.path[i][p].x > self.path[i][p + 1].x {
write!(f, "{}", "".blue())?; 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 { } else if self.map.get(x, y).blocked {
write!(f, "{}", "#")?; write!(f, "{}", "#")?;
} else if x % 8 == 0 || y % 8 == 0 {
write!(f, "")?;
} else { } else {
write!(f, " ")?; write!(f, " ")?;
} }
@ -143,10 +203,7 @@ impl<'a> WheightedGraph for MapInternal<'a> {
} else { } else {
let t = self.get_direction(*node); let t = self.get_direction(*node);
let v = t let v = t.iter().flatten();
.iter()
.flatten()
.filter_map(|&p| (!self.map.get(p.x, p.y).blocked).then_some(p));
v.count() v.count()
} }
@ -157,20 +214,21 @@ impl<'a> WheightedGraph for MapInternal<'a> {
t.iter() t.iter()
.flatten() .flatten()
.filter_map(|&p| (!self.map.get(p.x, p.y).blocked).then_some(p))
.nth(num) .nth(num)
.map(|p| (p, 1.0)) .map(|&p| (p, self.map.get(p.x, p.y).wheight))
} }
} }
impl Problem { impl Problem {
pub fn find_path(&mut self) { 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[i] = p;
if let Some(p) = p { }
self.path = p;
} }
} }
} }