Refactor Direction and Position.
This commit is contained in:
		
							parent
							
								
									2bdfd8cc6c
								
							
						
					
					
						commit
						9751764611
					
				
					 6 changed files with 206 additions and 220 deletions
				
			
		|  | @ -1,58 +0,0 @@ | ||||||
| use factorio_blueprint::belt_finding::{brute_force::BruteforceBuilder, Direction, Position}; |  | ||||||
| 
 |  | ||||||
| fn main() { |  | ||||||
|     let mut b = BruteforceBuilder::new(14, 6); |  | ||||||
| 
 |  | ||||||
|     b.add_path( |  | ||||||
|         (Position::new(0, 0), Direction::Right), |  | ||||||
|         (Position::new(13, 0), Direction::Right), |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     b.add_path( |  | ||||||
|         (Position::new(0, 1), Direction::Right), |  | ||||||
|         (Position::new(13, 1), Direction::Right), |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     b.add_path( |  | ||||||
|         (Position::new(0, 2), Direction::Right), |  | ||||||
|         (Position::new(13, 2), Direction::Right), |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     b.add_path( |  | ||||||
|         (Position::new(0, 3), Direction::Right), |  | ||||||
|         (Position::new(13, 3), Direction::Right), |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     b.add_path( |  | ||||||
|         (Position::new(0, 4), Direction::Right), |  | ||||||
|         (Position::new(13, 4), Direction::Right), |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     b.add_path( |  | ||||||
|         (Position::new(0, 5), Direction::Right), |  | ||||||
|         (Position::new(13, 5), Direction::Right), |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     // b.set_blocked_range(7, 2, 10, 2, true);
 |  | ||||||
|     // b.set_blocked_range(7, 3, 10, 4, true);
 |  | ||||||
| 
 |  | ||||||
|     b.set_blocked_range(3, 2, 10, 3, true); |  | ||||||
|     b.set_blocked(2, 0, true); |  | ||||||
|     b.set_blocked(11, 0, true); |  | ||||||
|     b.set_blocked(2, 5, true); |  | ||||||
|     b.set_blocked(11, 5, true); |  | ||||||
| 
 |  | ||||||
|     let mut b = b.build(); |  | ||||||
| 
 |  | ||||||
|     println!("{}\n{}\n{}", b.count(), b.solution_count(), b); |  | ||||||
|     while b.next_finish_state() { |  | ||||||
|         println!("{}\n{}\n{}", b.count(), b.solution_count(), b); |  | ||||||
|     } |  | ||||||
|     println!("{}\n{}", b.count(), b.solution_count()); |  | ||||||
| 
 |  | ||||||
|     // println!("{}\n{}", b.count(), b);
 |  | ||||||
| 
 |  | ||||||
|     // while b.next_state() {
 |  | ||||||
|     //     println!("{}\n{}", b.count(), b);
 |  | ||||||
|     // }
 |  | ||||||
| } |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| use factorio_blueprint::belt_finding::{Position, Problem}; | use factorio_blueprint::belt_finding::{common::Position, Problem}; | ||||||
| 
 | 
 | ||||||
| fn main() { | fn main() { | ||||||
|     let mut p = Problem::new(17, 13); |     let mut p = Problem::new(17, 13); | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| use factorio_blueprint::belt_finding::{Position, Problem}; | use factorio_blueprint::belt_finding::{common::Position, Problem}; | ||||||
| 
 | 
 | ||||||
| fn main() { | fn main() { | ||||||
|     let mut p = Problem::new(33, 13); |     let mut p = Problem::new(33, 13); | ||||||
|  |  | ||||||
|  | @ -4,7 +4,10 @@ use colored::Colorize; | ||||||
| 
 | 
 | ||||||
| use crate::misc::Map; | use crate::misc::Map; | ||||||
| 
 | 
 | ||||||
| use super::{Direction, Position, COLORS}; | use super::{ | ||||||
|  |     common::{Dimension, Direction, PathField}, | ||||||
|  |     Position, COLORS, | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| #[derive(Default, Clone)] | #[derive(Default, Clone)] | ||||||
| pub struct BruteforceField { | pub struct BruteforceField { | ||||||
|  | @ -13,43 +16,6 @@ pub struct BruteforceField { | ||||||
|     underground_horizontal: bool, |     underground_horizontal: bool, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug, Copy)] |  | ||||||
| pub enum PathField { |  | ||||||
|     Belt { |  | ||||||
|         pos: Position, |  | ||||||
|         dir: Direction, |  | ||||||
|     }, |  | ||||||
|     Underground { |  | ||||||
|         pos: Position, |  | ||||||
|         dir: Direction, |  | ||||||
|         len: u8, |  | ||||||
|     }, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl PathField { |  | ||||||
|     fn pos(&self) -> &Position { |  | ||||||
|         match self { |  | ||||||
|             PathField::Belt { pos, dir: _ } => pos, |  | ||||||
|             PathField::Underground { |  | ||||||
|                 pos, |  | ||||||
|                 dir: _, |  | ||||||
|                 len: _, |  | ||||||
|             } => pos, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn dir(&self) -> &Direction { |  | ||||||
|         match self { |  | ||||||
|             PathField::Belt { pos: _, dir } => dir, |  | ||||||
|             PathField::Underground { |  | ||||||
|                 pos: _, |  | ||||||
|                 dir, |  | ||||||
|                 len: _, |  | ||||||
|             } => dir, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static MAX_UNDERGROUND_LENGTH: u8 = 6; | static MAX_UNDERGROUND_LENGTH: u8 = 6; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
|  | @ -83,12 +49,18 @@ impl BruteforceBuilder { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn build(self) -> Bruteforce { |     pub fn build(self) -> Bruteforce { | ||||||
|  |         let dimension = Dimension { | ||||||
|  |             width: self.map.width, | ||||||
|  |             height: self.map.height, | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|         let mut b = Bruteforce { |         let mut b = Bruteforce { | ||||||
|             map: self.map, |             map: self.map, | ||||||
|             problems: Vec::new(), |             problems: Vec::new(), | ||||||
|             pointer_stack: vec![0], |             pointer_stack: vec![0], | ||||||
|             solution_count: 0, |             solution_count: 0, | ||||||
|             count: 0, |             count: 0, | ||||||
|  |             dimension, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         for [start, end] in self.path { |         for [start, end] in self.path { | ||||||
|  | @ -120,6 +92,7 @@ struct Problem { | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| pub struct Bruteforce { | pub struct Bruteforce { | ||||||
|     map: Map<BruteforceField>, |     map: Map<BruteforceField>, | ||||||
|  |     dimension: Dimension, | ||||||
|     problems: Vec<Problem>, |     problems: Vec<Problem>, | ||||||
|     pointer_stack: Vec<usize>, |     pointer_stack: Vec<usize>, | ||||||
|     solution_count: u128, |     solution_count: u128, | ||||||
|  | @ -145,7 +118,7 @@ impl Bruteforce { | ||||||
|                 self.map.get_mut(pos.x, pos.y).blocked = true; |                 self.map.get_mut(pos.x, pos.y).blocked = true; | ||||||
| 
 | 
 | ||||||
|                 for i in 0..=*len { |                 for i in 0..=*len { | ||||||
|                     let mid_pos = self.pos_in_direction(pos, dir, i.into()).unwrap(); |                     let mid_pos = pos.in_direction(dir, i.into(), &self.dimension).unwrap(); | ||||||
|                     if dir.vertical() { |                     if dir.vertical() { | ||||||
|                         self.map.get_mut(mid_pos.x, mid_pos.y).underground_vertical = true; |                         self.map.get_mut(mid_pos.x, mid_pos.y).underground_vertical = true; | ||||||
|                     } else { |                     } else { | ||||||
|  | @ -155,7 +128,7 @@ impl Bruteforce { | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 let end_pos = self.pos_in_direction(pos, dir, *len as usize).unwrap(); |                 let end_pos = { pos.in_direction(dir, *len as usize, &self.dimension) }.unwrap(); | ||||||
|                 self.map.get_mut(end_pos.x, end_pos.y).blocked = true; |                 self.map.get_mut(end_pos.x, end_pos.y).blocked = true; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -169,7 +142,7 @@ impl Bruteforce { | ||||||
|                 self.map.get_mut(pos.x, pos.y).blocked = false; |                 self.map.get_mut(pos.x, pos.y).blocked = false; | ||||||
| 
 | 
 | ||||||
|                 for i in 0..=len { |                 for i in 0..=len { | ||||||
|                     let mid_pos = self.pos_in_direction(&pos, &dir, i.into()).unwrap(); |                     let mid_pos = pos.in_direction(&dir, i.into(), &self.dimension).unwrap(); | ||||||
|                     if dir.vertical() { |                     if dir.vertical() { | ||||||
|                         self.map.get_mut(mid_pos.x, mid_pos.y).underground_vertical = false; |                         self.map.get_mut(mid_pos.x, mid_pos.y).underground_vertical = false; | ||||||
|                     } else { |                     } else { | ||||||
|  | @ -179,7 +152,7 @@ impl Bruteforce { | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 let end_pos = self.pos_in_direction(&pos, &dir, len.into()).unwrap(); |                 let end_pos = pos.in_direction(&dir, len.into(), &self.dimension).unwrap(); | ||||||
|                 self.map.get_mut(end_pos.x, end_pos.y).blocked = false; |                 self.map.get_mut(end_pos.x, end_pos.y).blocked = false; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -226,12 +199,14 @@ impl Bruteforce { | ||||||
|         match (last, &path_field) { |         match (last, &path_field) { | ||||||
|             (PathField::Belt { pos: _, dir: _ }, PathField::Belt { pos: _, dir: _ }) => {} |             (PathField::Belt { pos: _, dir: _ }, PathField::Belt { pos: _, dir: _ }) => {} | ||||||
|             (PathField::Belt { pos: _, dir: _ }, PathField::Underground { pos, dir, len }) => { |             (PathField::Belt { pos: _, dir: _ }, PathField::Underground { pos, dir, len }) => { | ||||||
|                 let end_pos = self.pos_in_direction(pos, dir, *len as usize).unwrap(); |                 let end_pos = pos | ||||||
|  |                     .in_direction(dir, *len as usize, &self.dimension) | ||||||
|  |                     .unwrap(); | ||||||
| 
 | 
 | ||||||
|                 self.map.get_mut(end_pos.x, end_pos.y).blocked = true; |                 self.map.get_mut(end_pos.x, end_pos.y).blocked = true; | ||||||
| 
 | 
 | ||||||
|                 for l in 0..=*len { |                 for l in 0..=*len { | ||||||
|                     let p = self.pos_in_direction(pos, dir, l as usize).unwrap(); |                     let p = pos.in_direction(dir, l as usize, &self.dimension).unwrap(); | ||||||
|                     match dir.vertical() { |                     match dir.vertical() { | ||||||
|                         true => self.map.get_mut(p.x, p.y).underground_vertical = true, |                         true => self.map.get_mut(p.x, p.y).underground_vertical = true, | ||||||
|                         false => self.map.get_mut(p.x, p.y).underground_horizontal = true, |                         false => self.map.get_mut(p.x, p.y).underground_horizontal = true, | ||||||
|  | @ -260,11 +235,11 @@ impl Bruteforce { | ||||||
|                     len: new_len, |                     len: new_len, | ||||||
|                 }, |                 }, | ||||||
|             ) => { |             ) => { | ||||||
|                 let last_end_pos = self |                 let last_end_pos = pos | ||||||
|                     .pos_in_direction(&pos, &dir, last_len as usize) |                     .in_direction(&dir, last_len as usize, &self.dimension) | ||||||
|                     .unwrap(); |                     .unwrap(); | ||||||
|                 let new_end_pos = self |                 let new_end_pos = pos | ||||||
|                     .pos_in_direction(&pos, &dir, *new_len as usize) |                     .in_direction(&dir, *new_len as usize, &self.dimension) | ||||||
|                     .unwrap(); |                     .unwrap(); | ||||||
| 
 | 
 | ||||||
|                 self.map.get_mut(last_end_pos.x, last_end_pos.y).blocked = false; |                 self.map.get_mut(last_end_pos.x, last_end_pos.y).blocked = false; | ||||||
|  | @ -273,7 +248,7 @@ impl Bruteforce { | ||||||
|                 match last_len < *new_len { |                 match last_len < *new_len { | ||||||
|                     true => { |                     true => { | ||||||
|                         for l in last_len + 1..=*new_len { |                         for l in last_len + 1..=*new_len { | ||||||
|                             let p = self.pos_in_direction(&pos, &dir, l as usize).unwrap(); |                             let p = pos.in_direction(&dir, l as usize, &self.dimension).unwrap(); | ||||||
|                             match dir.vertical() { |                             match dir.vertical() { | ||||||
|                                 true => self.map.get_mut(p.x, p.y).underground_vertical = true, |                                 true => self.map.get_mut(p.x, p.y).underground_vertical = true, | ||||||
|                                 false => self.map.get_mut(p.x, p.y).underground_horizontal = true, |                                 false => self.map.get_mut(p.x, p.y).underground_horizontal = true, | ||||||
|  | @ -293,14 +268,14 @@ impl Bruteforce { | ||||||
| 
 | 
 | ||||||
|     fn check_finish(&self, i: usize) -> bool { |     fn check_finish(&self, i: usize) -> bool { | ||||||
|         match self.problems[i].path.last().unwrap() { |         match self.problems[i].path.last().unwrap() { | ||||||
|             PathField::Belt { pos, dir } => self |             PathField::Belt { pos, dir } => pos | ||||||
|                 .pos_in_direction(pos, dir, 1) |                 .in_direction(dir, 1, &self.dimension) | ||||||
|                 .filter(|p| { |                 .filter(|p| { | ||||||
|                     p == &self.problems[i].end_pos && dir != &self.problems[i].end_dir.reverse() |                     p == &self.problems[i].end_pos && dir != &self.problems[i].end_dir.reverse() | ||||||
|                 }) |                 }) | ||||||
|                 .is_some(), |                 .is_some(), | ||||||
|             PathField::Underground { pos, dir, len } => self |             PathField::Underground { pos, dir, len } => pos | ||||||
|                 .pos_in_direction(pos, dir, *len as usize + 1) |                 .in_direction(dir, *len as usize + 1, &self.dimension) | ||||||
|                 .filter(|p| { |                 .filter(|p| { | ||||||
|                     p == &self.problems[i].end_pos && dir != &self.problems[i].end_dir.reverse() |                     p == &self.problems[i].end_pos && dir != &self.problems[i].end_dir.reverse() | ||||||
|                 }) |                 }) | ||||||
|  | @ -308,16 +283,6 @@ impl Bruteforce { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn path_field_end(&self, path_field: &PathField) -> (Position, Direction) { |  | ||||||
|         match path_field { |  | ||||||
|             PathField::Belt { pos, dir } => (*pos, *dir), |  | ||||||
|             PathField::Underground { pos, dir, len } => ( |  | ||||||
|                 self.pos_in_direction(pos, dir, *len as usize).unwrap(), |  | ||||||
|                 *dir, |  | ||||||
|             ), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn modify_underground(&mut self, pos: &Position, dir: &Direction, len: u8) -> bool { |     fn modify_underground(&mut self, pos: &Position, dir: &Direction, len: u8) -> bool { | ||||||
|         if len >= MAX_UNDERGROUND_LENGTH { |         if len >= MAX_UNDERGROUND_LENGTH { | ||||||
|             return false; |             return false; | ||||||
|  | @ -332,7 +297,7 @@ impl Bruteforce { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         let end_pos = match self.pos_in_direction(pos, dir, len as usize) { |         let end_pos = match pos.in_direction(dir, len as usize, &self.dimension) { | ||||||
|             Some(s) => s, |             Some(s) => s, | ||||||
|             None => { |             None => { | ||||||
|                 return false; |                 return false; | ||||||
|  | @ -430,7 +395,13 @@ impl Bruteforce { | ||||||
|                     if second_last.dir().counter_clockwise() == dir |                     if second_last.dir().counter_clockwise() == dir | ||||||
|                         && self.modify_underground(&pos, second_last.dir(), 2) |                         && self.modify_underground(&pos, second_last.dir(), 2) | ||||||
|                     { |                     { | ||||||
|                         let (p, d) = self.path_field_end(self.modify_path().last().unwrap()); |                         let (p, d) = self | ||||||
|  |                             .modify_path() | ||||||
|  |                             .last() | ||||||
|  |                             .unwrap() | ||||||
|  |                             .end_pos(&self.dimension) | ||||||
|  |                             .unwrap(); | ||||||
|  | 
 | ||||||
|                         if self.is_next_free(&p, &d) { |                         if self.is_next_free(&p, &d) { | ||||||
|                             return true; |                             return true; | ||||||
|                         } else { |                         } else { | ||||||
|  | @ -440,7 +411,13 @@ impl Bruteforce { | ||||||
|                 } |                 } | ||||||
|                 PathField::Underground { pos, dir, len } => { |                 PathField::Underground { pos, dir, len } => { | ||||||
|                     if self.modify_underground(&pos, &dir, len + 1) { |                     if self.modify_underground(&pos, &dir, len + 1) { | ||||||
|                         let (p, d) = self.path_field_end(self.modify_path().last().unwrap()); |                         let (p, d) = self | ||||||
|  |                             .modify_path() | ||||||
|  |                             .last() | ||||||
|  |                             .unwrap() | ||||||
|  |                             .end_pos(&self.dimension) | ||||||
|  |                             .unwrap(); | ||||||
|  | 
 | ||||||
|                         if self.is_next_free(&p, &d) { |                         if self.is_next_free(&p, &d) { | ||||||
|                             return true; |                             return true; | ||||||
|                         } else { |                         } else { | ||||||
|  | @ -472,16 +449,21 @@ impl Bruteforce { | ||||||
| 
 | 
 | ||||||
|     fn is_next_free(&self, pos: &Position, dir: &Direction) -> bool { |     fn is_next_free(&self, pos: &Position, dir: &Direction) -> bool { | ||||||
|         let i = self.modify_pointer(); |         let i = self.modify_pointer(); | ||||||
|         self.pos_in_direction(pos, dir, 1) |         { pos.in_direction(dir, 1, &self.dimension) } | ||||||
|             .filter(|p| !self.map.get(p.x, p.y).blocked || self.problems[i].end_pos == *p) |             .filter(|p| !self.map.get(p.x, p.y).blocked || self.problems[i].end_pos == *p) | ||||||
|             .is_some() |             .is_some() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Add an Path elemeent
 |     // Add an Path elemeent
 | ||||||
|     fn add(&mut self) -> bool { |     fn add(&mut self) -> bool { | ||||||
|         let (pos, dir) = self.path_field_end(self.add_path().last().unwrap()); |         let (pos, dir) = self | ||||||
|  |             .add_path() | ||||||
|  |             .last() | ||||||
|  |             .unwrap() | ||||||
|  |             .end_pos(&self.dimension) | ||||||
|  |             .unwrap(); | ||||||
| 
 | 
 | ||||||
|         if let Some(p) = self.pos_in_direction(&pos, &dir, 1) { |         if let Some(p) = pos.in_direction(&dir, 1, &self.dimension) { | ||||||
|             if !self.map.get(p.x, p.y).blocked { |             if !self.map.get(p.x, p.y).blocked { | ||||||
|                 self.apply_path_field(PathField::Belt { pos: p, dir }); |                 self.apply_path_field(PathField::Belt { pos: p, dir }); | ||||||
|                 return self.is_next_free(&p, &dir); |                 return self.is_next_free(&p, &dir); | ||||||
|  | @ -535,19 +517,6 @@ impl Bruteforce { | ||||||
|             .sum() |             .sum() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn pos_in_direction(&self, pos: &Position, dir: &Direction, len: usize) -> Option<Position> { |  | ||||||
|         match dir { |  | ||||||
|             Direction::Up => pos.y.checked_sub(len).map(|y| Position::new(pos.x, y)), |  | ||||||
|             Direction::Right => Some(pos.x + len) |  | ||||||
|                 .filter(|&x| x < self.map.width) |  | ||||||
|                 .map(|x| Position::new(x, pos.y)), |  | ||||||
|             Direction::Down => Some(pos.y + len) |  | ||||||
|                 .filter(|&y| y < self.map.height) |  | ||||||
|                 .map(|y| Position::new(pos.x, y)), |  | ||||||
|             Direction::Left => pos.x.checked_sub(len).map(|x| Position::new(x, pos.y)), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn count(&self) -> u128 { |     pub fn count(&self) -> u128 { | ||||||
|         self.count |         self.count | ||||||
|     } |     } | ||||||
|  | @ -605,7 +574,9 @@ impl Display for Bruteforce { | ||||||
|                             Direction::Down => 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, "↞"))), |                             Direction::Left => m.set(pos.x, pos.y, Some((i, "↞"))), | ||||||
|                         }; |                         }; | ||||||
|                         let end_pos = self.pos_in_direction(pos, dir, *len as usize).unwrap(); |                         let end_pos = pos | ||||||
|  |                             .in_direction(dir, *len as usize, &self.dimension) | ||||||
|  |                             .unwrap(); | ||||||
|                         match dir { |                         match dir { | ||||||
|                             Direction::Up => m.set(end_pos.x, end_pos.y, Some((i, "↥"))), |                             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::Right => m.set(end_pos.x, end_pos.y, Some((i, "↦"))), | ||||||
|  |  | ||||||
							
								
								
									
										146
									
								
								src/belt_finding/common.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								src/belt_finding/common.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,146 @@ | ||||||
|  | #[derive(Clone, Copy, PartialEq, Eq, Debug)] | ||||||
|  | pub enum Direction { | ||||||
|  |     Up, | ||||||
|  |     Right, | ||||||
|  |     Down, | ||||||
|  |     Left, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Direction { | ||||||
|  |     pub fn from_neghbors(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; | ||||||
|  | 
 | ||||||
|  |         match (x_diff, y_diff) { | ||||||
|  |             (1, 0) => Direction::Left, | ||||||
|  |             (0, 1) => Direction::Up, | ||||||
|  |             (-1, 0) => Direction::Right, | ||||||
|  |             (0, -1) => Direction::Down, | ||||||
|  |             _ => { | ||||||
|  |                 panic!("Positions are not neighbors.") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn vertical(&self) -> bool { | ||||||
|  |         match self { | ||||||
|  |             Direction::Up => true, | ||||||
|  |             Direction::Right => false, | ||||||
|  |             Direction::Down => true, | ||||||
|  |             Direction::Left => false, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn horizontal(&self) -> bool { | ||||||
|  |         !self.vertical() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn reverse(&self) -> Self { | ||||||
|  |         match self { | ||||||
|  |             Direction::Up => Direction::Down, | ||||||
|  |             Direction::Right => Direction::Left, | ||||||
|  |             Direction::Down => Direction::Up, | ||||||
|  |             Direction::Left => Direction::Right, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn clockwise(&self) -> Self { | ||||||
|  |         match self { | ||||||
|  |             Direction::Up => Direction::Right, | ||||||
|  |             Direction::Right => Direction::Down, | ||||||
|  |             Direction::Down => Direction::Left, | ||||||
|  |             Direction::Left => Direction::Up, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn counter_clockwise(&self) -> Self { | ||||||
|  |         match self { | ||||||
|  |             Direction::Up => Direction::Left, | ||||||
|  |             Direction::Right => Direction::Up, | ||||||
|  |             Direction::Down => Direction::Right, | ||||||
|  |             Direction::Left => Direction::Down, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||||||
|  | pub struct Position { | ||||||
|  |     pub x: usize, | ||||||
|  |     pub y: usize, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||||||
|  | pub struct Dimension { | ||||||
|  |     pub width: usize, | ||||||
|  |     pub height: usize, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Position { | ||||||
|  |     pub fn new(x: usize, y: usize) -> Self { | ||||||
|  |         Self { x, y } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn in_direction( | ||||||
|  |         &self, | ||||||
|  |         dir: &Direction, | ||||||
|  |         len: usize, | ||||||
|  |         dimension: &Dimension, | ||||||
|  |     ) -> Option<Position> { | ||||||
|  |         match dir { | ||||||
|  |             Direction::Up => self.y.checked_sub(len).map(|y| Position::new(self.x, y)), | ||||||
|  |             Direction::Right => Some(self.x + len) | ||||||
|  |                 .filter(|&x| x < dimension.width) | ||||||
|  |                 .map(|x| Position::new(x, self.y)), | ||||||
|  |             Direction::Down => Some(self.y + len) | ||||||
|  |                 .filter(|&y| y < dimension.height) | ||||||
|  |                 .map(|y| Position::new(self.x, y)), | ||||||
|  |             Direction::Left => self.x.checked_sub(len).map(|x| Position::new(x, self.y)), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, Copy)] | ||||||
|  | pub enum PathField { | ||||||
|  |     Belt { | ||||||
|  |         pos: Position, | ||||||
|  |         dir: Direction, | ||||||
|  |     }, | ||||||
|  |     Underground { | ||||||
|  |         pos: Position, | ||||||
|  |         dir: Direction, | ||||||
|  |         len: u8, | ||||||
|  |     }, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl PathField { | ||||||
|  |     pub fn pos(&self) -> &Position { | ||||||
|  |         match self { | ||||||
|  |             PathField::Belt { pos, dir: _ } => pos, | ||||||
|  |             PathField::Underground { | ||||||
|  |                 pos, | ||||||
|  |                 dir: _, | ||||||
|  |                 len: _, | ||||||
|  |             } => pos, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn dir(&self) -> &Direction { | ||||||
|  |         match self { | ||||||
|  |             PathField::Belt { pos: _, dir } => dir, | ||||||
|  |             PathField::Underground { | ||||||
|  |                 pos: _, | ||||||
|  |                 dir, | ||||||
|  |                 len: _, | ||||||
|  |             } => dir, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn end_pos(&self, dimension: &Dimension) -> Option<(Position, Direction)> { | ||||||
|  |         match self { | ||||||
|  |             PathField::Belt { pos, dir } => Some((*pos, *dir)), | ||||||
|  |             PathField::Underground { pos, dir, len } => pos | ||||||
|  |                 .in_direction(dir, *len as usize, dimension) | ||||||
|  |                 .map(|p| (p, *dir)), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| use crate::belt_finding::brute_force::BruteforceBuilder; | use crate::belt_finding::{brute_force::BruteforceBuilder, common::Direction}; | ||||||
| use crate::graph::wheighted_graph::shortest_path::dijkstra; | use crate::graph::wheighted_graph::shortest_path::dijkstra; | ||||||
| use crate::graph::wheighted_graph::WheightedGraph; | use crate::graph::wheighted_graph::WheightedGraph; | ||||||
| use crate::misc::Map; | use crate::misc::Map; | ||||||
|  | @ -6,83 +6,10 @@ use crate::priority_queue::BinaryHeap; | ||||||
| use colored::{Color, Colorize}; | use colored::{Color, Colorize}; | ||||||
| use std::fmt::Display; | use std::fmt::Display; | ||||||
| 
 | 
 | ||||||
|  | use self::common::Position; | ||||||
|  | 
 | ||||||
| pub mod brute_force; | pub mod brute_force; | ||||||
| 
 | pub mod common; | ||||||
| #[derive(Clone, Copy, PartialEq, Eq, Debug)] |  | ||||||
| pub enum Direction { |  | ||||||
|     Up, |  | ||||||
|     Right, |  | ||||||
|     Down, |  | ||||||
|     Left, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Direction { |  | ||||||
|     fn from_neghbors(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; |  | ||||||
| 
 |  | ||||||
|         match (x_diff, y_diff) { |  | ||||||
|             (1, 0) => Direction::Left, |  | ||||||
|             (0, 1) => Direction::Up, |  | ||||||
|             (-1, 0) => Direction::Right, |  | ||||||
|             (0, -1) => Direction::Down, |  | ||||||
|             _ => { |  | ||||||
|                 unreachable!() |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn vertical(&self) -> bool { |  | ||||||
|         match self { |  | ||||||
|             Direction::Up => true, |  | ||||||
|             Direction::Right => false, |  | ||||||
|             Direction::Down => true, |  | ||||||
|             Direction::Left => false, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // fn horizontal(&self) -> bool {
 |  | ||||||
|     //     !self.vertical()
 |  | ||||||
|     // }
 |  | ||||||
| 
 |  | ||||||
|     fn reverse(&self) -> Self { |  | ||||||
|         match self { |  | ||||||
|             Direction::Up => Direction::Down, |  | ||||||
|             Direction::Right => Direction::Left, |  | ||||||
|             Direction::Down => Direction::Up, |  | ||||||
|             Direction::Left => Direction::Right, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn clockwise(&self) -> Self { |  | ||||||
|         match self { |  | ||||||
|             Direction::Up => Direction::Right, |  | ||||||
|             Direction::Right => Direction::Down, |  | ||||||
|             Direction::Down => Direction::Left, |  | ||||||
|             Direction::Left => Direction::Up, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn counter_clockwise(&self) -> Self { |  | ||||||
|         match self { |  | ||||||
|             Direction::Up => Direction::Left, |  | ||||||
|             Direction::Right => Direction::Up, |  | ||||||
|             Direction::Down => Direction::Right, |  | ||||||
|             Direction::Left => Direction::Down, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |  | ||||||
| pub struct Position { |  | ||||||
|     pub x: usize, |  | ||||||
|     pub y: usize, |  | ||||||
| } |  | ||||||
| impl Position { |  | ||||||
|     pub fn new(x: usize, y: usize) -> Self { |  | ||||||
|         Self { x, y } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| #[derive(Default, Clone, Copy)] | #[derive(Default, Clone, Copy)] | ||||||
| pub struct Field { | pub struct Field { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue