Add candidate selection.
This commit is contained in:
parent
207a0436d8
commit
8f6809c17f
3 changed files with 148 additions and 50 deletions
|
|
@ -14,6 +14,7 @@ enum Mode {
|
|||
enum ProblemCase {
|
||||
Level1,
|
||||
Level2,
|
||||
Level3,
|
||||
}
|
||||
|
||||
impl ProblemCase {
|
||||
|
|
@ -21,6 +22,7 @@ impl ProblemCase {
|
|||
match self {
|
||||
ProblemCase::Level1 => problems::belt_madness_level_1(),
|
||||
ProblemCase::Level2 => problems::belt_madness_level_2(),
|
||||
ProblemCase::Level3 => problems::belt_madness_level_3(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,48 @@ pub struct ConflictAvoidance {
|
|||
belts: Vec<Vec<PathField>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct Candidate {
|
||||
min: Position,
|
||||
max: Position,
|
||||
}
|
||||
|
||||
impl Candidate {
|
||||
fn new(min: Position, max: Position) -> Self {
|
||||
Self { min, max }
|
||||
}
|
||||
|
||||
fn area(&self) -> PositionType {
|
||||
(self.max.x - self.min.x) * (self.max.y - self.min.y)
|
||||
}
|
||||
fn extend_range(&mut self, conflict_map: &Map<usize>) {
|
||||
for x in self.min.x..=self.max.x {
|
||||
if self.min.y > 0 && *conflict_map.get(x as usize, self.min.y as usize) > 1 {
|
||||
self.min.y -= 1;
|
||||
return self.extend_range(conflict_map);
|
||||
}
|
||||
if (self.max.y as usize) < conflict_map.height - 1
|
||||
&& *conflict_map.get(x as usize, self.max.y as usize) > 1
|
||||
{
|
||||
self.max.y += 1;
|
||||
return self.extend_range(conflict_map);
|
||||
}
|
||||
}
|
||||
for y in self.min.y..=self.max.y {
|
||||
if self.min.x > 0 && *conflict_map.get(self.min.x as usize, y as usize) > 1 {
|
||||
self.min.x -= 1;
|
||||
return self.extend_range(conflict_map);
|
||||
}
|
||||
if (self.max.x as usize) < conflict_map.width - 1
|
||||
&& *conflict_map.get(self.max.x as usize, y as usize) > 1
|
||||
{
|
||||
self.max.x += 1;
|
||||
return self.extend_range(conflict_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConflictAvoidance {
|
||||
pub fn new(problem: Problem) -> Self {
|
||||
let mut map: Map<Field> = Map::new(problem.map.width, problem.map.height);
|
||||
|
|
@ -50,33 +92,6 @@ impl ConflictAvoidance {
|
|||
Self { map, belts }
|
||||
}
|
||||
|
||||
fn extend_range(
|
||||
conflict_map: &Map<usize>,
|
||||
xrange: &mut RangeInclusive<usize>,
|
||||
yrange: &mut RangeInclusive<usize>,
|
||||
) {
|
||||
for x in xrange.clone() {
|
||||
if *yrange.start() > 0 && *conflict_map.get(x, *yrange.start()) > 1 {
|
||||
*yrange = *yrange.start() - 1..=*yrange.end();
|
||||
return Self::extend_range(conflict_map, xrange, yrange);
|
||||
}
|
||||
if *yrange.end() < conflict_map.height - 1 && *conflict_map.get(x, *yrange.end()) > 1 {
|
||||
*yrange = *yrange.start()..=*yrange.end() + 1;
|
||||
return Self::extend_range(conflict_map, xrange, yrange);
|
||||
}
|
||||
}
|
||||
for y in yrange.clone() {
|
||||
if *xrange.start() > 0 && *conflict_map.get(*xrange.start(), y) > 1 {
|
||||
*xrange = *xrange.start() - 1..=*xrange.end();
|
||||
return Self::extend_range(conflict_map, xrange, yrange);
|
||||
}
|
||||
if *xrange.end() < conflict_map.width - 1 && *conflict_map.get(*xrange.end(), y) > 1 {
|
||||
*xrange = *xrange.start()..=*xrange.end() + 1;
|
||||
return Self::extend_range(conflict_map, xrange, yrange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_conflict(&mut self) -> bool {
|
||||
let mut conflicts: Map<usize> = Map::new(self.map.width, self.map.height);
|
||||
|
||||
|
|
@ -114,37 +129,32 @@ impl ConflictAvoidance {
|
|||
println!();
|
||||
}
|
||||
|
||||
let mut c = None;
|
||||
let mut candidates = Vec::new();
|
||||
|
||||
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 mut candidate = Candidate::new(
|
||||
Position::new(x as PositionType, y as PositionType),
|
||||
Position::new(x as PositionType, y as PositionType),
|
||||
);
|
||||
candidate.extend_range(&conflicts);
|
||||
if !candidates.iter().any(|c| c == &candidate) {
|
||||
candidates.push(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (cx, cy) = match c {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
if candidates.is_empty() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
let xoffset = 1;
|
||||
let yoffset = 1;
|
||||
|
||||
let mut xrange = cx..=cx;
|
||||
let mut yrange = cy..=cy;
|
||||
|
||||
loop {
|
||||
xrange = xrange.start().saturating_sub(xoffset)
|
||||
..=usize::min(xrange.end() + xoffset, self.map.width - 1);
|
||||
yrange = yrange.start().saturating_sub(yoffset)
|
||||
..=usize::min(yrange.end() + yoffset, self.map.height - 1);
|
||||
|
||||
println!("x: {:?}, y: {:?}", xrange, yrange);
|
||||
Self::extend_range(&conflicts, &mut xrange, &mut yrange);
|
||||
candidates.sort_by_key(|c| -c.area());
|
||||
let c = candidates.pop().unwrap();
|
||||
let mut xrange = c.min.x as usize..=c.max.x as usize;
|
||||
let mut yrange = c.min.y as usize..=c.max.y as usize;
|
||||
|
||||
println!("x: {:?}, y: {:?}", xrange, yrange);
|
||||
|
||||
|
|
@ -261,6 +271,57 @@ impl ConflictAvoidance {
|
|||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
let mut candidate = Candidate::new(
|
||||
Position::new(
|
||||
xrange.start().saturating_sub(1) as PositionType,
|
||||
*yrange.start() as PositionType,
|
||||
),
|
||||
Position::new(*xrange.end() as PositionType, *yrange.end() as PositionType),
|
||||
);
|
||||
candidate.extend_range(&conflicts);
|
||||
if candidate != c && !candidates.iter().any(|c| c == &candidate) {
|
||||
candidates.push(candidate);
|
||||
}
|
||||
let mut candidate = Candidate::new(
|
||||
Position::new(
|
||||
*xrange.start() as PositionType,
|
||||
yrange.start().saturating_sub(1) as PositionType,
|
||||
),
|
||||
Position::new(*xrange.end() as PositionType, *yrange.end() as PositionType),
|
||||
);
|
||||
candidate.extend_range(&conflicts);
|
||||
if candidate != c && !candidates.iter().any(|c| c == &candidate) {
|
||||
candidates.push(candidate);
|
||||
}
|
||||
let mut candidate = Candidate::new(
|
||||
Position::new(
|
||||
*xrange.start() as PositionType,
|
||||
*yrange.start() as PositionType,
|
||||
),
|
||||
Position::new(
|
||||
usize::min(xrange.end() + 1, self.map.width - 1) as PositionType,
|
||||
*yrange.end() as PositionType,
|
||||
),
|
||||
);
|
||||
candidate.extend_range(&conflicts);
|
||||
if candidate != c && !candidates.iter().any(|c| c == &candidate) {
|
||||
candidates.push(candidate);
|
||||
}
|
||||
let mut candidate = Candidate::new(
|
||||
Position::new(
|
||||
*xrange.start() as PositionType,
|
||||
*yrange.start() as PositionType,
|
||||
),
|
||||
Position::new(
|
||||
*xrange.end() as PositionType,
|
||||
usize::min(yrange.end() + 1, self.map.height - 1) as PositionType,
|
||||
),
|
||||
);
|
||||
candidate.extend_range(&conflicts);
|
||||
if candidate != c && !candidates.iter().any(|c| c == &candidate) {
|
||||
candidates.push(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,13 +84,19 @@ impl Problem {
|
|||
}
|
||||
}
|
||||
|
||||
static COLORS: [Color; 6] = [
|
||||
static COLORS: [Color; 12] = [
|
||||
Color::Red,
|
||||
Color::Green,
|
||||
Color::Yellow,
|
||||
Color::Blue,
|
||||
Color::Magenta,
|
||||
Color::Cyan,
|
||||
Color::BrightRed,
|
||||
Color::BrightGreen,
|
||||
Color::BrightYellow,
|
||||
Color::BrightBlue,
|
||||
Color::BrightMagenta,
|
||||
Color::Cyan,
|
||||
];
|
||||
|
||||
impl Display for Problem {
|
||||
|
|
@ -277,6 +283,35 @@ pub mod problems {
|
|||
}
|
||||
|
||||
pub fn belt_madness_level_2() -> Problem {
|
||||
let mut p = Problem::new(17, 13);
|
||||
p.set_blocked(0, 3, true);
|
||||
|
||||
p.set_blocked_range(1, 2, 2, 5, true);
|
||||
p.set_blocked_range(1, 7, 2, 10, true);
|
||||
|
||||
p.set_blocked(0, 9, true);
|
||||
|
||||
p.set_blocked(16, 3, true);
|
||||
|
||||
p.set_blocked_range(14, 2, 15, 5, true);
|
||||
p.set_blocked_range(14, 7, 15, 10, true);
|
||||
|
||||
p.set_blocked(16, 9, true);
|
||||
|
||||
p.add_connection(Position::new(3, 4), Position::new(13, 2));
|
||||
p.add_connection(Position::new(3, 7), Position::new(13, 3));
|
||||
p.add_connection(Position::new(3, 10), Position::new(13, 4));
|
||||
p.add_connection(Position::new(3, 9), Position::new(13, 5));
|
||||
|
||||
p.add_connection(Position::new(3, 2), Position::new(13, 7));
|
||||
p.add_connection(Position::new(3, 3), Position::new(13, 8));
|
||||
p.add_connection(Position::new(3, 5), Position::new(13, 9));
|
||||
p.add_connection(Position::new(3, 8), Position::new(13, 10));
|
||||
|
||||
p
|
||||
}
|
||||
|
||||
pub fn belt_madness_level_3() -> Problem {
|
||||
let mut p = Problem::new(33, 13);
|
||||
|
||||
p.set_blocked_range(1, 3, 2, 5, true);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue