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 { | enum ProblemCase { | ||||||
|     Level1, |     Level1, | ||||||
|     Level2, |     Level2, | ||||||
|  |     Level3, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ProblemCase { | impl ProblemCase { | ||||||
|  | @ -21,6 +22,7 @@ impl ProblemCase { | ||||||
|         match self { |         match self { | ||||||
|             ProblemCase::Level1 => problems::belt_madness_level_1(), |             ProblemCase::Level1 => problems::belt_madness_level_1(), | ||||||
|             ProblemCase::Level2 => problems::belt_madness_level_2(), |             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>>, |     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 { | impl ConflictAvoidance { | ||||||
|     pub fn new(problem: Problem) -> Self { |     pub fn new(problem: Problem) -> Self { | ||||||
|         let mut map: Map<Field> = Map::new(problem.map.width, problem.map.height); |         let mut map: Map<Field> = Map::new(problem.map.width, problem.map.height); | ||||||
|  | @ -50,33 +92,6 @@ impl ConflictAvoidance { | ||||||
|         Self { map, belts } |         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 { |     pub fn remove_conflict(&mut self) -> bool { | ||||||
|         let mut conflicts: Map<usize> = Map::new(self.map.width, self.map.height); |         let mut conflicts: Map<usize> = Map::new(self.map.width, self.map.height); | ||||||
| 
 | 
 | ||||||
|  | @ -114,37 +129,32 @@ impl ConflictAvoidance { | ||||||
|             println!(); |             println!(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         let mut c = None; |         let mut candidates = Vec::new(); | ||||||
|  | 
 | ||||||
|         for y in 0..self.map.height { |         for y in 0..self.map.height { | ||||||
|             for x in 0..self.map.width { |             for x in 0..self.map.width { | ||||||
|                 if *conflicts.get(x, y) > 1 { |                 if *conflicts.get(x, y) > 1 { | ||||||
|                     c = Some((x, y)); |                     let mut candidate = Candidate::new( | ||||||
|                     break; |                         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 { |         if candidates.is_empty() { | ||||||
|             Some(c) => c, |             return false; | ||||||
|             None => { |         } | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         let xoffset = 1; |  | ||||||
|         let yoffset = 1; |  | ||||||
| 
 |  | ||||||
|         let mut xrange = cx..=cx; |  | ||||||
|         let mut yrange = cy..=cy; |  | ||||||
| 
 | 
 | ||||||
|         loop { |         loop { | ||||||
|             xrange = xrange.start().saturating_sub(xoffset) |             candidates.sort_by_key(|c| -c.area()); | ||||||
|                 ..=usize::min(xrange.end() + xoffset, self.map.width - 1); |             let c = candidates.pop().unwrap(); | ||||||
|             yrange = yrange.start().saturating_sub(yoffset) |             let mut xrange = c.min.x as usize..=c.max.x as usize; | ||||||
|                 ..=usize::min(yrange.end() + yoffset, self.map.height - 1); |             let mut yrange = c.min.y as usize..=c.max.y as usize; | ||||||
| 
 |  | ||||||
|             println!("x: {:?}, y: {:?}", xrange, yrange); |  | ||||||
|             Self::extend_range(&conflicts, &mut xrange, &mut yrange); |  | ||||||
| 
 | 
 | ||||||
|             println!("x: {:?}, y: {:?}", xrange, yrange); |             println!("x: {:?}, y: {:?}", xrange, yrange); | ||||||
| 
 | 
 | ||||||
|  | @ -261,6 +271,57 @@ impl ConflictAvoidance { | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 return true; |                 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::Red, | ||||||
|     Color::Green, |     Color::Green, | ||||||
|     Color::Yellow, |     Color::Yellow, | ||||||
|     Color::Blue, |     Color::Blue, | ||||||
|     Color::Magenta, |     Color::Magenta, | ||||||
|     Color::Cyan, |     Color::Cyan, | ||||||
|  |     Color::BrightRed, | ||||||
|  |     Color::BrightGreen, | ||||||
|  |     Color::BrightYellow, | ||||||
|  |     Color::BrightBlue, | ||||||
|  |     Color::BrightMagenta, | ||||||
|  |     Color::Cyan, | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| impl Display for Problem { | impl Display for Problem { | ||||||
|  | @ -277,6 +283,35 @@ pub mod problems { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn belt_madness_level_2() -> Problem { |     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); |         let mut p = Problem::new(33, 13); | ||||||
| 
 | 
 | ||||||
|         p.set_blocked_range(1, 3, 2, 5, true); |         p.set_blocked_range(1, 3, 2, 5, true); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue