Initial conflict avoidance.
This commit is contained in:
parent
9751764611
commit
993fb0730c
4 changed files with 480 additions and 185 deletions
|
|
@ -1,57 +1,55 @@
|
|||
use factorio_blueprint::belt_finding::{common::Position, Problem};
|
||||
use clap::{Parser, ValueEnum};
|
||||
use factorio_blueprint::belt_finding::{conflict_avoidance::ConflictAvoidance, problems, Problem};
|
||||
|
||||
#[derive(ValueEnum, Clone)]
|
||||
enum Mode {
|
||||
Solve,
|
||||
ConflictAvoidance,
|
||||
}
|
||||
|
||||
#[derive(ValueEnum, Clone)]
|
||||
enum ProblemCase {
|
||||
Level1,
|
||||
Level2,
|
||||
}
|
||||
|
||||
impl ProblemCase {
|
||||
fn get_problem(&self) -> Problem {
|
||||
match self {
|
||||
ProblemCase::Level1 => problems::belt_madness_level_1(),
|
||||
ProblemCase::Level2 => problems::belt_madness_level_2(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Args {
|
||||
#[arg(value_enum, default_value = "level1")]
|
||||
problem: ProblemCase,
|
||||
#[arg(value_enum, default_value = "solve")]
|
||||
mode: Mode,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut p = Problem::new(17, 13);
|
||||
let args = Args::parse();
|
||||
|
||||
p.set_blocked(0, 3, true);
|
||||
let mut p = args.problem.get_problem();
|
||||
|
||||
p.set_blocked(1, 4, true);
|
||||
p.set_blocked(2, 4, true);
|
||||
p.set_blocked(1, 5, true);
|
||||
p.set_blocked(2, 5, true);
|
||||
|
||||
p.set_blocked(1, 7, true);
|
||||
p.set_blocked(2, 7, true);
|
||||
p.set_blocked(1, 8, true);
|
||||
p.set_blocked(2, 8, true);
|
||||
|
||||
p.set_blocked(0, 9, true);
|
||||
|
||||
p.set_blocked(16, 3, true);
|
||||
|
||||
p.set_blocked(14, 4, true);
|
||||
p.set_blocked(15, 4, true);
|
||||
p.set_blocked(14, 5, true);
|
||||
p.set_blocked(15, 5, true);
|
||||
|
||||
p.set_blocked(14, 7, true);
|
||||
p.set_blocked(15, 7, true);
|
||||
p.set_blocked(14, 8, true);
|
||||
p.set_blocked(15, 8, 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);
|
||||
p.find_path();
|
||||
println!("{}", p);
|
||||
match args.mode {
|
||||
Mode::Solve => {
|
||||
println!("{}", p);
|
||||
p.find_path();
|
||||
println!("{}", p);
|
||||
}
|
||||
Mode::ConflictAvoidance => {
|
||||
println!("{}", p);
|
||||
p.find_path();
|
||||
println!("{}", p);
|
||||
let mut c = ConflictAvoidance::new(p);
|
||||
println!("{}", c);
|
||||
while c.remove_conflict() {
|
||||
println!("{}", c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ pub enum Direction {
|
|||
}
|
||||
|
||||
impl Direction {
|
||||
pub fn from_neghbors(pos: &Position, neighbor: &Position) -> Self {
|
||||
pub fn from_neighbors(pos: &Position, neighbor: &Position) -> Self {
|
||||
let x_diff = pos.x as i64 - neighbor.x as i64;
|
||||
let y_diff = pos.y as i64 - neighbor.y as i64;
|
||||
|
||||
|
|
@ -143,4 +143,24 @@ impl PathField {
|
|||
.map(|p| (p, *dir)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offset(&self, offset: (i32, i32)) -> Self {
|
||||
match self {
|
||||
PathField::Belt { pos, dir } => PathField::Belt {
|
||||
pos: Position::new(
|
||||
(pos.x as i32 + offset.0) as usize,
|
||||
(pos.y as i32 + offset.1) as usize,
|
||||
),
|
||||
dir: *dir,
|
||||
},
|
||||
PathField::Underground { pos, dir, len } => PathField::Underground {
|
||||
pos: Position::new(
|
||||
(pos.x as i32 + offset.0) as usize,
|
||||
(pos.y as i32 + offset.1) as usize,
|
||||
),
|
||||
dir: *dir,
|
||||
len: *len,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
335
src/belt_finding/conflict_avoidance.rs
Normal file
335
src/belt_finding/conflict_avoidance.rs
Normal file
|
|
@ -0,0 +1,335 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use colored::Colorize;
|
||||
|
||||
use crate::{belt_finding::brute_force::BruteforceBuilder, misc::Map};
|
||||
|
||||
use super::{
|
||||
common::{Dimension, Direction, PathField, Position},
|
||||
Problem, COLORS,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
struct Field {
|
||||
blocked: bool,
|
||||
}
|
||||
|
||||
pub struct ConflictAvoidance {
|
||||
map: Map<Field>,
|
||||
belts: Vec<Vec<PathField>>,
|
||||
}
|
||||
|
||||
impl ConflictAvoidance {
|
||||
pub fn new(problem: Problem) -> Self {
|
||||
let mut map: Map<Field> = Map::new(problem.map.width, problem.map.height);
|
||||
for x in 0..problem.map.width {
|
||||
for y in 0..problem.map.height {
|
||||
map.get_mut(x, y).blocked = problem.map.get(x, y).blocked;
|
||||
}
|
||||
}
|
||||
let mut belts = Vec::new();
|
||||
for i in 0..problem.path.len() {
|
||||
let mut p = Vec::new();
|
||||
|
||||
for j in 0..problem.path[i].len() - 1 {
|
||||
p.push(PathField::Belt {
|
||||
pos: problem.path[i][j],
|
||||
dir: Direction::from_neighbors(&problem.path[i][j], &problem.path[i][j + 1]),
|
||||
});
|
||||
}
|
||||
|
||||
p.push(PathField::Belt {
|
||||
pos: *problem.path[i].last().unwrap(),
|
||||
dir: *p.last().unwrap().dir(),
|
||||
});
|
||||
|
||||
belts.push(p);
|
||||
}
|
||||
|
||||
Self { map, belts }
|
||||
}
|
||||
|
||||
pub fn remove_conflict(&mut self) -> bool {
|
||||
let mut conflicts: Map<usize> = Map::new(self.map.width, self.map.height);
|
||||
|
||||
for x in 0..self.map.width {
|
||||
for y in 0..self.map.height {
|
||||
if self.map.get(x, y).blocked {
|
||||
*conflicts.get_mut(x, y) += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for path in &self.belts {
|
||||
for p in path {
|
||||
match p {
|
||||
PathField::Belt { pos, dir: _ } => *conflicts.get_mut(pos.x, pos.y) += 1,
|
||||
PathField::Underground { pos, dir, len } => {
|
||||
*conflicts.get_mut(pos.x, pos.y) += 1;
|
||||
let end = pos
|
||||
.in_direction(
|
||||
dir,
|
||||
*len as usize,
|
||||
&Dimension {
|
||||
width: self.map.width,
|
||||
height: self.map.height,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
*conflicts.get_mut(end.x, end.y) += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for y in 0..self.map.height {
|
||||
for x in 0..self.map.width {
|
||||
if *conflicts.get(x, y) > 1 {
|
||||
print!("#");
|
||||
} else {
|
||||
print!(" ");
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
let mut c = None;
|
||||
for y in 0..self.map.height {
|
||||
for x in 0..self.map.width {
|
||||
if *conflicts.get(x, y) > 1 {
|
||||
c = Some((x, y));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (cx, cy) = match c {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
let mut xoffset = 0;
|
||||
let mut yoffset = 0;
|
||||
|
||||
loop {
|
||||
xoffset += 1;
|
||||
yoffset += 1;
|
||||
|
||||
let xrange = cx..=cx;
|
||||
let yrange = cy..=cy;
|
||||
|
||||
let xrange = xrange.start().saturating_sub(xoffset)
|
||||
..=usize::min(xrange.end() + xoffset, self.map.width - 1);
|
||||
let yrange = yrange.start().saturating_sub(yoffset)
|
||||
..=usize::min(yrange.end() + yoffset, self.map.height - 1);
|
||||
|
||||
println!("x: {:?}, y: {:?}", xrange, yrange);
|
||||
|
||||
let xsize = xrange.end() - xrange.start() + 1;
|
||||
let ysize = yrange.end() - yrange.start() + 1;
|
||||
|
||||
// dbg!(xsize, ysize);
|
||||
|
||||
let mut b = BruteforceBuilder::new(xsize + 2, ysize + 2);
|
||||
b.set_blocked_range(0, 0, xsize + 1, 0, true);
|
||||
b.set_blocked_range(0, ysize + 1, xsize + 1, ysize + 1, true);
|
||||
b.set_blocked_range(0, 0, 0, ysize + 1, true);
|
||||
b.set_blocked_range(xsize + 1, 0, xsize + 1, ysize + 1, true);
|
||||
|
||||
for x in 0..xsize {
|
||||
for y in 0..ysize {
|
||||
b.set_blocked(
|
||||
x + 1,
|
||||
y + 1,
|
||||
self.map.get(xrange.start() + x, yrange.start() + y).blocked,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let mut mapping = Vec::new();
|
||||
|
||||
for (i, path) in self.belts.iter().enumerate() {
|
||||
let s = path
|
||||
.iter()
|
||||
.map(|p| p.pos())
|
||||
.position(|p| xrange.contains(&p.x) && yrange.contains(&p.y))
|
||||
.map(|i| i.saturating_sub(1));
|
||||
let e = path
|
||||
.iter()
|
||||
.map(|p| p.pos())
|
||||
.rev()
|
||||
.position(|p| xrange.contains(&p.x) && yrange.contains(&p.y))
|
||||
.map(|i| usize::min(path.len() - 1, path.len() - i));
|
||||
|
||||
if let Some((start, end)) = s.zip(e) {
|
||||
// dbg!(start, end);
|
||||
mapping.push((i, start, end));
|
||||
|
||||
// dbg!(path[start], path[end]);
|
||||
|
||||
let (start_pos, start_dir) = path[start]
|
||||
.end_pos(&Dimension {
|
||||
width: self.map.width,
|
||||
height: self.map.height,
|
||||
})
|
||||
.unwrap();
|
||||
let end_pos = path[end].pos();
|
||||
let end_dir = path[end].dir();
|
||||
|
||||
// dbg!(start_pos, end_pos);
|
||||
|
||||
b.add_path(
|
||||
(
|
||||
Position::new(
|
||||
start_pos.x - (xrange.start() - 1),
|
||||
start_pos.y - (yrange.start() - 1),
|
||||
),
|
||||
start_dir,
|
||||
),
|
||||
(
|
||||
Position::new(
|
||||
end_pos.x - (xrange.start() - 1),
|
||||
end_pos.y - (yrange.start() - 1),
|
||||
),
|
||||
*end_dir,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
println!("{:?}", mapping);
|
||||
|
||||
let mut b = b.build();
|
||||
|
||||
println!("{}", b);
|
||||
|
||||
let mut min_cost = f64::INFINITY;
|
||||
let mut solutions = Vec::new();
|
||||
|
||||
while b.next_finish_state() {
|
||||
// println!("{}", b);
|
||||
let c = b.cost();
|
||||
if c < min_cost {
|
||||
min_cost = c;
|
||||
solutions = b.get_paths();
|
||||
}
|
||||
}
|
||||
|
||||
println!("{}", b.solution_count());
|
||||
|
||||
if b.solution_count() > 0 {
|
||||
for (p, (index, start, end)) in solutions.iter().zip(mapping) {
|
||||
let mut t = Vec::new();
|
||||
|
||||
t.extend_from_slice(&self.belts[index][0..=start]);
|
||||
t.extend(p[1..].iter().map(|p| {
|
||||
p.offset(((*xrange.start() as i32) - 1, (*yrange.start() as i32) - 1))
|
||||
}));
|
||||
t.extend_from_slice(&self.belts[index][end..]);
|
||||
// println!("{:?}", &t);
|
||||
// println!("{:?}", &self.belts[index]);
|
||||
|
||||
self.belts[index] = t;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_all_conflicts(&mut self) {
|
||||
while self.remove_conflict() {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ConflictAvoidance {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let width_digits = self.map.width.ilog10() + 1;
|
||||
let height_digits = self.map.height.ilog10() + 1;
|
||||
|
||||
// print header
|
||||
for i in 0..width_digits {
|
||||
let d = width_digits - i - 1;
|
||||
// padding
|
||||
for _ in 0..height_digits {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
|
||||
for x in 0..self.map.width {
|
||||
let digits = x / (usize::pow(10, d));
|
||||
if digits == 0 && d > 0 {
|
||||
write!(f, " ")?;
|
||||
} else {
|
||||
write!(f, "{}", char::from_u32((digits % 10) as u32 + 48).unwrap())?;
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(f)?;
|
||||
}
|
||||
|
||||
let mut m: Map<Option<(usize, &str)>> = Map::new(self.map.width, self.map.height);
|
||||
|
||||
for (i, problem) in self.belts.iter().enumerate() {
|
||||
for p in problem {
|
||||
match p {
|
||||
PathField::Belt { pos, dir } => match dir {
|
||||
Direction::Up => m.set(pos.x, pos.y, Some((i, "↑"))),
|
||||
Direction::Right => m.set(pos.x, pos.y, Some((i, "→"))),
|
||||
Direction::Down => m.set(pos.x, pos.y, Some((i, "↓"))),
|
||||
Direction::Left => m.set(pos.x, pos.y, Some((i, "←"))),
|
||||
},
|
||||
PathField::Underground { pos, dir, len } => {
|
||||
match dir {
|
||||
Direction::Up => m.set(pos.x, pos.y, Some((i, "↟"))),
|
||||
Direction::Right => m.set(pos.x, pos.y, Some((i, "↠"))),
|
||||
Direction::Down => m.set(pos.x, pos.y, Some((i, "↡"))),
|
||||
Direction::Left => m.set(pos.x, pos.y, Some((i, "↞"))),
|
||||
};
|
||||
let end_pos = pos
|
||||
.in_direction(
|
||||
dir,
|
||||
*len as usize,
|
||||
&Dimension {
|
||||
width: self.map.width,
|
||||
height: self.map.height,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
match dir {
|
||||
Direction::Up => m.set(end_pos.x, end_pos.y, Some((i, "↥"))),
|
||||
Direction::Right => m.set(end_pos.x, end_pos.y, Some((i, "↦"))),
|
||||
Direction::Down => m.set(end_pos.x, end_pos.y, Some((i, "↧"))),
|
||||
Direction::Left => m.set(end_pos.x, end_pos.y, Some((i, "↤"))),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
let last_pos = problem.last().unwrap().pos();
|
||||
m.set(last_pos.x, last_pos.y, Some((i, "T")));
|
||||
}
|
||||
|
||||
// Print body
|
||||
|
||||
for y in 0..self.map.height {
|
||||
write!(f, "{:1$}", y, height_digits as usize)?;
|
||||
|
||||
for x in 0..self.map.width {
|
||||
if let Some((i, c)) = m.get(x, y) {
|
||||
write!(f, "{}", c.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, " ")?;
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(f)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ use self::common::Position;
|
|||
|
||||
pub mod brute_force;
|
||||
pub mod common;
|
||||
pub mod conflict_avoidance;
|
||||
|
||||
#[derive(Default, Clone, Copy)]
|
||||
pub struct Field {
|
||||
|
|
@ -216,137 +217,78 @@ impl Problem {
|
|||
self.path[i] = p;
|
||||
}
|
||||
}
|
||||
|
||||
let mut conflicts: Map<usize> = Map::new(self.map.width, self.map.height);
|
||||
|
||||
for x in 0..self.map.width {
|
||||
for y in 0..self.map.height {
|
||||
if self.map.get(x, y).blocked {
|
||||
*conflicts.get_mut(x, y) += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for path in &self.path {
|
||||
for pos in path {
|
||||
*conflicts.get_mut(pos.x, pos.y) += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for y in 0..self.map.height {
|
||||
for x in 0..self.map.width {
|
||||
if *conflicts.get(x, y) > 1 {
|
||||
print!("#");
|
||||
} else {
|
||||
print!(" ");
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
println!("{self}");
|
||||
|
||||
loop {
|
||||
let mut c = None;
|
||||
for y in 0..self.map.height {
|
||||
for x in 0..self.map.width {
|
||||
if *conflicts.get(x, y) > 1 {
|
||||
c = Some((x, y));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dbg!(c);
|
||||
|
||||
let xoffset = 2;
|
||||
let yoffset = 2;
|
||||
|
||||
if let Some((cx, cy)) = c {
|
||||
*conflicts.get_mut(cx, cy) = 1;
|
||||
|
||||
let xrange = cx..=cx;
|
||||
let yrange = cy..=cy;
|
||||
|
||||
let xrange = xrange.start().saturating_sub(xoffset)
|
||||
..=usize::min(xrange.end() + xoffset, self.map.width - 1);
|
||||
let yrange = yrange.start().saturating_sub(yoffset)
|
||||
..=usize::min(yrange.end() + yoffset, self.map.height - 1);
|
||||
// dbg!(&xrange, &yrange);
|
||||
|
||||
let xsize = xrange.end() - xrange.start() + 1;
|
||||
let ysize = yrange.end() - yrange.start() + 1;
|
||||
|
||||
// dbg!(xsize, ysize);
|
||||
|
||||
let mut b = BruteforceBuilder::new(xsize + 2, ysize + 2);
|
||||
b.set_blocked_range(0, 0, xsize + 1, 0, true);
|
||||
b.set_blocked_range(0, ysize + 1, xsize + 1, ysize + 1, true);
|
||||
b.set_blocked_range(0, 0, 0, ysize + 1, true);
|
||||
b.set_blocked_range(xsize + 1, 0, xsize + 1, ysize + 1, true);
|
||||
|
||||
for x in 0..xsize {
|
||||
for y in 0..ysize {
|
||||
b.set_blocked(
|
||||
x + 1,
|
||||
y + 1,
|
||||
self.map.get(xrange.start() + x, yrange.start() + y).blocked,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for path in &self.path {
|
||||
let s = path
|
||||
.iter()
|
||||
.position(|p| xrange.contains(&p.x) && yrange.contains(&p.y))
|
||||
.map(|i| i.saturating_sub(1));
|
||||
let e = path
|
||||
.iter()
|
||||
.rev()
|
||||
.position(|p| xrange.contains(&p.x) && yrange.contains(&p.y))
|
||||
.map(|i| usize::min(path.len() - 1, path.len() - i));
|
||||
|
||||
if let Some((start, end)) = s.zip(e) {
|
||||
// dbg!(start, end);
|
||||
|
||||
let start_pos = path[start];
|
||||
let start_dir = Direction::from_neghbors(&path[start], &path[start + 1]);
|
||||
let end_pos = path[end];
|
||||
let end_dir = Direction::from_neghbors(&path[end - 1], &path[end]);
|
||||
|
||||
// dbg!(start_pos, end_pos);
|
||||
|
||||
b.add_path(
|
||||
(
|
||||
Position::new(
|
||||
start_pos.x - (xrange.start() - 1),
|
||||
start_pos.y - (yrange.start() - 1),
|
||||
),
|
||||
start_dir,
|
||||
),
|
||||
(
|
||||
Position::new(
|
||||
end_pos.x - (xrange.start() - 1),
|
||||
end_pos.y - (yrange.start() - 1),
|
||||
),
|
||||
end_dir,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let mut b = b.build();
|
||||
|
||||
println!("{}", b);
|
||||
|
||||
while b.next_finish_state() {
|
||||
println!("{}", b);
|
||||
}
|
||||
|
||||
println!("{}", b.solution_count());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod problems {
|
||||
use super::{common::Position, Problem};
|
||||
|
||||
pub fn belt_madness_level_1() -> Problem {
|
||||
let mut p = Problem::new(17, 13);
|
||||
|
||||
p.set_blocked(0, 3, true);
|
||||
|
||||
p.set_blocked(1, 4, true);
|
||||
p.set_blocked(2, 4, true);
|
||||
p.set_blocked(1, 5, true);
|
||||
p.set_blocked(2, 5, true);
|
||||
|
||||
p.set_blocked(1, 7, true);
|
||||
p.set_blocked(2, 7, true);
|
||||
p.set_blocked(1, 8, true);
|
||||
p.set_blocked(2, 8, true);
|
||||
|
||||
p.set_blocked(0, 9, true);
|
||||
|
||||
p.set_blocked(16, 3, true);
|
||||
|
||||
p.set_blocked(14, 4, true);
|
||||
p.set_blocked(15, 4, true);
|
||||
p.set_blocked(14, 5, true);
|
||||
p.set_blocked(15, 5, true);
|
||||
|
||||
p.set_blocked(14, 7, true);
|
||||
p.set_blocked(15, 7, true);
|
||||
p.set_blocked(14, 8, true);
|
||||
p.set_blocked(15, 8, 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
|
||||
}
|
||||
|
||||
pub fn belt_madness_level_2() -> Problem {
|
||||
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));
|
||||
|
||||
p
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue