Use PositionType for position
This commit is contained in:
parent
2e9c699600
commit
207a0436d8
4 changed files with 283 additions and 194 deletions
|
|
@ -5,7 +5,7 @@ use colored::Colorize;
|
|||
use crate::misc::Map;
|
||||
|
||||
use super::{
|
||||
common::{Dimension, Direction, PathField},
|
||||
common::{Dimension, Direction, PathField, PositionType},
|
||||
Position, COLORS,
|
||||
};
|
||||
|
||||
|
|
@ -64,8 +64,10 @@ impl BruteforceBuilder {
|
|||
};
|
||||
|
||||
for [start, end] in self.path {
|
||||
b.map.get_mut(start.0.x, start.0.y).blocked = true;
|
||||
b.map.get_mut(end.0.x, end.0.y).blocked = true;
|
||||
b.map
|
||||
.get_mut(start.0.x as usize, start.0.y as usize)
|
||||
.blocked = true;
|
||||
b.map.get_mut(end.0.x as usize, end.0.y as usize).blocked = true;
|
||||
b.problems.push(Problem {
|
||||
path: vec![PathField::Belt {
|
||||
pos: start.0,
|
||||
|
|
@ -111,25 +113,32 @@ impl Bruteforce {
|
|||
self.pointer_stack.last().copied().unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Path field must be valid and inside bounds.
|
||||
fn internal_apply_path_field(&mut self, i: usize, path_field: PathField) {
|
||||
match &path_field {
|
||||
PathField::Belt { pos, dir: _ } => self.map.get_mut(pos.x, pos.y).blocked = true,
|
||||
PathField::Belt { pos, dir: _ } => {
|
||||
self.map.get_mut(pos.x as usize, pos.y as usize).blocked = true
|
||||
}
|
||||
PathField::Underground { pos, dir, len } => {
|
||||
self.map.get_mut(pos.x, pos.y).blocked = true;
|
||||
self.map.get_mut(pos.x as usize, pos.y as usize).blocked = true;
|
||||
|
||||
for i in 0..=*len {
|
||||
let mid_pos = pos.in_direction(dir, i.into(), &self.dimension).unwrap();
|
||||
let mid_pos = pos.in_direction(dir, i as PositionType);
|
||||
if dir.vertical() {
|
||||
self.map.get_mut(mid_pos.x, mid_pos.y).underground_vertical = true;
|
||||
self.map
|
||||
.get_mut(mid_pos.x as usize, mid_pos.y as usize)
|
||||
.underground_vertical = true;
|
||||
} else {
|
||||
self.map
|
||||
.get_mut(mid_pos.x, mid_pos.y)
|
||||
.get_mut(mid_pos.x as usize, mid_pos.y as usize)
|
||||
.underground_horizontal = true;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
let end_pos = pos.in_direction(dir, *len as PositionType);
|
||||
self.map
|
||||
.get_mut(end_pos.x as usize, end_pos.y as usize)
|
||||
.blocked = true;
|
||||
}
|
||||
}
|
||||
self.problems[i].path.push(path_field);
|
||||
|
|
@ -137,23 +146,29 @@ impl Bruteforce {
|
|||
|
||||
fn internal_remove_path_field(&mut self, i: usize) {
|
||||
match self.problems[i].path.pop().unwrap() {
|
||||
PathField::Belt { pos, dir: _ } => self.map.get_mut(pos.x, pos.y).blocked = false,
|
||||
PathField::Belt { pos, dir: _ } => {
|
||||
self.map.get_mut(pos.x as usize, pos.y as usize).blocked = false
|
||||
}
|
||||
PathField::Underground { pos, dir, len } => {
|
||||
self.map.get_mut(pos.x, pos.y).blocked = false;
|
||||
self.map.get_mut(pos.x as usize, pos.y as usize).blocked = false;
|
||||
|
||||
for i in 0..=len {
|
||||
let mid_pos = pos.in_direction(&dir, i.into(), &self.dimension).unwrap();
|
||||
let mid_pos = pos.in_direction(&dir, i as PositionType);
|
||||
if dir.vertical() {
|
||||
self.map.get_mut(mid_pos.x, mid_pos.y).underground_vertical = false;
|
||||
self.map
|
||||
.get_mut(mid_pos.x as usize, mid_pos.y as usize)
|
||||
.underground_vertical = false;
|
||||
} else {
|
||||
self.map
|
||||
.get_mut(mid_pos.x, mid_pos.y)
|
||||
.get_mut(mid_pos.x as usize, mid_pos.y as usize)
|
||||
.underground_horizontal = false;
|
||||
}
|
||||
}
|
||||
|
||||
let end_pos = pos.in_direction(&dir, len.into(), &self.dimension).unwrap();
|
||||
self.map.get_mut(end_pos.x, end_pos.y).blocked = false;
|
||||
let end_pos = pos.in_direction(&dir, len.into());
|
||||
self.map
|
||||
.get_mut(end_pos.x as usize, end_pos.y as usize)
|
||||
.blocked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -199,17 +214,25 @@ impl Bruteforce {
|
|||
match (last, &path_field) {
|
||||
(PathField::Belt { pos: _, dir: _ }, PathField::Belt { pos: _, dir: _ }) => {}
|
||||
(PathField::Belt { pos: _, dir: _ }, PathField::Underground { pos, dir, len }) => {
|
||||
let end_pos = pos
|
||||
.in_direction(dir, *len as usize, &self.dimension)
|
||||
.unwrap();
|
||||
let end_pos = pos.in_direction(dir, *len as PositionType);
|
||||
|
||||
self.map.get_mut(end_pos.x, end_pos.y).blocked = true;
|
||||
self.map
|
||||
.get_mut(end_pos.x as usize, end_pos.y as usize)
|
||||
.blocked = true;
|
||||
|
||||
for l in 0..=*len {
|
||||
let p = pos.in_direction(dir, l as usize, &self.dimension).unwrap();
|
||||
let p = pos.in_direction(dir, l as PositionType);
|
||||
match dir.vertical() {
|
||||
true => self.map.get_mut(p.x, p.y).underground_vertical = true,
|
||||
false => self.map.get_mut(p.x, p.y).underground_horizontal = true,
|
||||
true => {
|
||||
self.map
|
||||
.get_mut(p.x as usize, p.y as usize)
|
||||
.underground_vertical = true
|
||||
}
|
||||
false => {
|
||||
self.map
|
||||
.get_mut(p.x as usize, p.y as usize)
|
||||
.underground_horizontal = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -235,23 +258,31 @@ impl Bruteforce {
|
|||
len: new_len,
|
||||
},
|
||||
) => {
|
||||
let last_end_pos = pos
|
||||
.in_direction(&dir, last_len as usize, &self.dimension)
|
||||
.unwrap();
|
||||
let new_end_pos = pos
|
||||
.in_direction(&dir, *new_len as usize, &self.dimension)
|
||||
.unwrap();
|
||||
let last_end_pos = pos.in_direction(&dir, last_len as PositionType);
|
||||
let new_end_pos = pos.in_direction(&dir, *new_len as PositionType);
|
||||
|
||||
self.map.get_mut(last_end_pos.x, last_end_pos.y).blocked = false;
|
||||
self.map.get_mut(new_end_pos.x, new_end_pos.y).blocked = true;
|
||||
self.map
|
||||
.get_mut(last_end_pos.x as usize, last_end_pos.y as usize)
|
||||
.blocked = false;
|
||||
self.map
|
||||
.get_mut(new_end_pos.x as usize, new_end_pos.y as usize)
|
||||
.blocked = true;
|
||||
|
||||
match last_len < *new_len {
|
||||
true => {
|
||||
for l in last_len + 1..=*new_len {
|
||||
let p = pos.in_direction(&dir, l as usize, &self.dimension).unwrap();
|
||||
let p = pos.in_direction(&dir, l as PositionType);
|
||||
match dir.vertical() {
|
||||
true => self.map.get_mut(p.x, p.y).underground_vertical = true,
|
||||
false => self.map.get_mut(p.x, p.y).underground_horizontal = true,
|
||||
true => {
|
||||
self.map
|
||||
.get_mut(p.x as usize, p.y as usize)
|
||||
.underground_vertical = true
|
||||
}
|
||||
false => {
|
||||
self.map
|
||||
.get_mut(p.x as usize, p.y as usize)
|
||||
.underground_horizontal = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -268,18 +299,18 @@ impl Bruteforce {
|
|||
|
||||
fn check_finish(&self, i: usize) -> bool {
|
||||
match self.problems[i].path.last().unwrap() {
|
||||
PathField::Belt { pos, dir } => pos
|
||||
.in_direction(dir, 1, &self.dimension)
|
||||
.filter(|p| {
|
||||
p == &self.problems[i].end_pos && dir != &self.problems[i].end_dir.reverse()
|
||||
})
|
||||
.is_some(),
|
||||
PathField::Underground { pos, dir, len } => pos
|
||||
.in_direction(dir, *len as usize + 1, &self.dimension)
|
||||
PathField::Belt { pos, dir } => Some(pos.in_direction(dir, 1))
|
||||
.filter(|p| {
|
||||
p == &self.problems[i].end_pos && dir != &self.problems[i].end_dir.reverse()
|
||||
})
|
||||
.is_some(),
|
||||
PathField::Underground { pos, dir, len } => {
|
||||
Some(pos.in_direction(dir, *len as PositionType + 1))
|
||||
.filter(|p| {
|
||||
p == &self.problems[i].end_pos && dir != &self.problems[i].end_dir.reverse()
|
||||
})
|
||||
.is_some()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -290,28 +321,49 @@ impl Bruteforce {
|
|||
|
||||
if len == 2
|
||||
&& match dir.vertical() {
|
||||
true => self.map.get(pos.x, pos.y).underground_vertical,
|
||||
false => self.map.get(pos.x, pos.y).underground_horizontal,
|
||||
true => {
|
||||
self.map
|
||||
.get(pos.x as usize, pos.y as usize)
|
||||
.underground_vertical
|
||||
}
|
||||
false => {
|
||||
self.map
|
||||
.get(pos.x as usize, pos.y as usize)
|
||||
.underground_horizontal
|
||||
}
|
||||
}
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
let end_pos = match pos.in_direction(dir, len as usize, &self.dimension) {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
return false;
|
||||
}
|
||||
let binding = pos.in_direction(dir, len as PositionType);
|
||||
let end_pos = match binding.in_range(
|
||||
&Position::new(0, 0),
|
||||
&Position::new(
|
||||
self.map.width as PositionType,
|
||||
self.map.height as PositionType,
|
||||
),
|
||||
) {
|
||||
Some(t) => t,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
if match dir.vertical() {
|
||||
true => self.map.get(end_pos.x, end_pos.y).underground_vertical,
|
||||
false => self.map.get(end_pos.x, end_pos.y).underground_horizontal,
|
||||
true => {
|
||||
self.map
|
||||
.get(end_pos.x as usize, end_pos.y as usize)
|
||||
.underground_vertical
|
||||
}
|
||||
false => {
|
||||
self.map
|
||||
.get(end_pos.x as usize, end_pos.y as usize)
|
||||
.underground_horizontal
|
||||
}
|
||||
} {
|
||||
return false;
|
||||
}
|
||||
|
||||
if !self.map.get(end_pos.x, end_pos.y).blocked {
|
||||
if !self.map.get(end_pos.x as usize, end_pos.y as usize).blocked {
|
||||
self.modify_path_field(PathField::Underground {
|
||||
pos: *pos,
|
||||
dir: *dir,
|
||||
|
|
@ -395,12 +447,7 @@ impl Bruteforce {
|
|||
if second_last.dir().counter_clockwise() == dir
|
||||
&& self.modify_underground(&pos, second_last.dir(), 2)
|
||||
{
|
||||
let (p, d) = self
|
||||
.modify_path()
|
||||
.last()
|
||||
.unwrap()
|
||||
.end_pos(&self.dimension)
|
||||
.unwrap();
|
||||
let (p, d) = self.modify_path().last().unwrap().end_pos();
|
||||
|
||||
if self.is_next_free(&p, &d) {
|
||||
return true;
|
||||
|
|
@ -411,12 +458,7 @@ impl Bruteforce {
|
|||
}
|
||||
PathField::Underground { pos, dir, len } => {
|
||||
if self.modify_underground(&pos, &dir, len + 1) {
|
||||
let (p, d) = self
|
||||
.modify_path()
|
||||
.last()
|
||||
.unwrap()
|
||||
.end_pos(&self.dimension)
|
||||
.unwrap();
|
||||
let (p, d) = self.modify_path().last().unwrap().end_pos();
|
||||
|
||||
if self.is_next_free(&p, &d) {
|
||||
return true;
|
||||
|
|
@ -449,22 +491,32 @@ impl Bruteforce {
|
|||
|
||||
fn is_next_free(&self, pos: &Position, dir: &Direction) -> bool {
|
||||
let i = self.modify_pointer();
|
||||
{ pos.in_direction(dir, 1, &self.dimension) }
|
||||
.filter(|p| !self.map.get(p.x, p.y).blocked || self.problems[i].end_pos == *p)
|
||||
pos.in_direction(dir, 1)
|
||||
.in_range(
|
||||
&Position::new(0, 0),
|
||||
&Position::new(
|
||||
self.map.width as PositionType,
|
||||
self.map.height as PositionType,
|
||||
),
|
||||
)
|
||||
.filter(|&p| {
|
||||
!self.map.get(p.x as usize, p.y as usize).blocked || self.problems[i].end_pos == *p
|
||||
})
|
||||
.is_some()
|
||||
}
|
||||
|
||||
// Add an Path elemeent
|
||||
fn add(&mut self) -> bool {
|
||||
let (pos, dir) = self
|
||||
.add_path()
|
||||
.last()
|
||||
.unwrap()
|
||||
.end_pos(&self.dimension)
|
||||
.unwrap();
|
||||
let (pos, dir) = self.add_path().last().unwrap().end_pos();
|
||||
|
||||
if let Some(p) = pos.in_direction(&dir, 1, &self.dimension) {
|
||||
if !self.map.get(p.x, p.y).blocked {
|
||||
if let Some(&p) = pos.in_direction(&dir, 1).in_range(
|
||||
&Position::new(0, 0),
|
||||
&Position::new(
|
||||
self.map.width as PositionType,
|
||||
self.map.height as PositionType,
|
||||
),
|
||||
) {
|
||||
if !self.map.get(p.x as usize, p.y as usize).blocked {
|
||||
self.apply_path_field(PathField::Belt { pos: p, dir });
|
||||
return self.is_next_free(&p, &dir);
|
||||
}
|
||||
|
|
@ -555,33 +607,53 @@ impl Display for Bruteforce {
|
|||
|
||||
for (i, problem) in self.problems.iter().enumerate() {
|
||||
if problem.finished {
|
||||
m.set(problem.end_pos.x, problem.end_pos.y, Some((i, "T")));
|
||||
m.set(
|
||||
problem.end_pos.x as usize,
|
||||
problem.end_pos.y as usize,
|
||||
Some((i, "T")),
|
||||
);
|
||||
} else {
|
||||
m.set(problem.end_pos.x, problem.end_pos.y, Some((i, "t")));
|
||||
m.set(
|
||||
problem.end_pos.x as usize,
|
||||
problem.end_pos.y as usize,
|
||||
Some((i, "t")),
|
||||
);
|
||||
}
|
||||
for p in &problem.path {
|
||||
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, "←"))),
|
||||
Direction::Up => m.set(pos.x as usize, pos.y as usize, Some((i, "↑"))),
|
||||
Direction::Right => m.set(pos.x as usize, pos.y as usize, Some((i, "→"))),
|
||||
Direction::Down => m.set(pos.x as usize, pos.y as usize, Some((i, "↓"))),
|
||||
Direction::Left => m.set(pos.x as usize, pos.y as usize, 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, "↞"))),
|
||||
Direction::Up => m.set(pos.x as usize, pos.y as usize, Some((i, "↟"))),
|
||||
Direction::Right => {
|
||||
m.set(pos.x as usize, pos.y as usize, Some((i, "↠")))
|
||||
}
|
||||
Direction::Down => {
|
||||
m.set(pos.x as usize, pos.y as usize, Some((i, "↡")))
|
||||
}
|
||||
Direction::Left => {
|
||||
m.set(pos.x as usize, pos.y as usize, Some((i, "↞")))
|
||||
}
|
||||
};
|
||||
let end_pos = pos
|
||||
.in_direction(dir, *len as usize, &self.dimension)
|
||||
.unwrap();
|
||||
let end_pos = pos.in_direction(dir, *len as PositionType);
|
||||
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, "↤"))),
|
||||
Direction::Up => {
|
||||
m.set(end_pos.x as usize, end_pos.y as usize, Some((i, "↥")))
|
||||
}
|
||||
Direction::Right => {
|
||||
m.set(end_pos.x as usize, end_pos.y as usize, Some((i, "↦")))
|
||||
}
|
||||
Direction::Down => {
|
||||
m.set(end_pos.x as usize, end_pos.y as usize, Some((i, "↧")))
|
||||
}
|
||||
Direction::Left => {
|
||||
m.set(end_pos.x as usize, end_pos.y as usize, Some((i, "↤")))
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue