progress on this horrible pathfinding
it kinda works but last_direction doesn't funciton
This commit is contained in:
parent
9651b3a12c
commit
70e56f94db
1 changed files with 120 additions and 29 deletions
|
@ -1,12 +1,13 @@
|
|||
use crate::utils::Day;
|
||||
use array2d::Array2D;
|
||||
use itertools::Itertools;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Day17 {
|
||||
pub input: String,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub enum Direction {
|
||||
North,
|
||||
East,
|
||||
|
@ -14,13 +15,38 @@ pub enum Direction {
|
|||
West,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct State {
|
||||
cost: usize,
|
||||
x: usize,
|
||||
y: usize,
|
||||
row: usize,
|
||||
column: usize,
|
||||
tentative_distance: Option<usize>,
|
||||
last_direction: Option<Direction>,
|
||||
moves_without_turn: Option<u8>,
|
||||
moves_in_same_direction: Option<u8>,
|
||||
prev: Option<(usize, usize)>
|
||||
}
|
||||
|
||||
impl Day17 {
|
||||
pub fn calculate_node(current: &State, node: &mut State, direction: Direction) {
|
||||
let new_distance = current.tentative_distance.unwrap_or_default() + node.cost;
|
||||
if node.tentative_distance.is_some_and(|d| d > new_distance) || node.tentative_distance.is_none() {
|
||||
node.prev = Some((current.row, current.column));
|
||||
node.tentative_distance = Some(new_distance);
|
||||
node.last_direction = Some(
|
||||
match (node.row as isize - current.row as isize, node.column as isize - current.column as isize) {
|
||||
(0, -1) => Direction::West,
|
||||
(0, 1) => Direction::East,
|
||||
(1, 0) => Direction::South,
|
||||
(-1, 0) => Direction::North,
|
||||
_ => panic!()
|
||||
}
|
||||
);
|
||||
node.moves_in_same_direction = Some(match current.last_direction == node.last_direction {
|
||||
true => current.moves_in_same_direction.unwrap() + 1,
|
||||
false => 0
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Day for Day17 {
|
||||
|
@ -32,46 +58,111 @@ impl Day for Day17 {
|
|||
self.input.split('\n').enumerate().flat_map(|(i, str)| {
|
||||
str.chars().enumerate().map(move |(j, b)| State {
|
||||
cost: b.to_digit(10).unwrap() as usize,
|
||||
x: i,
|
||||
y: j,
|
||||
tentative_distance: if i == 0 && j == 0 {
|
||||
Some(b.to_digit(10).unwrap() as usize)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
moves_without_turn: if i == 0 && j == 0 {
|
||||
Some(1)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
last_direction: if i == 0 && j == 0 {
|
||||
Some(Direction::East)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
column: j,
|
||||
row: i,
|
||||
tentative_distance: None,
|
||||
moves_in_same_direction: None,
|
||||
last_direction: None,
|
||||
prev: None
|
||||
})
|
||||
}),
|
||||
rows,
|
||||
columns,
|
||||
)
|
||||
.unwrap();
|
||||
let unvisited = Vec::<(usize, usize)>::from_iter(
|
||||
let mut unvisited = Vec::<(usize, usize)>::from_iter(
|
||||
(0..columns).flat_map(|i| (0..rows).map(move |j| (i, j))),
|
||||
);
|
||||
let mut current = (0usize, 0usize);
|
||||
let mut current_pos = (0usize, 0usize);
|
||||
|
||||
loop {
|
||||
let current = &parsed[current];
|
||||
let current = parsed[current_pos].clone();
|
||||
|
||||
if current.last_direction != Some(Direction::South)
|
||||
&& !(current.last_direction == Some(Direction::North)
|
||||
&& current.moves_in_same_direction == Some(2))
|
||||
&& let Some(neighbor) = parsed.get_mut(current.row.wrapping_sub(1), current.column)
|
||||
{
|
||||
// Going north
|
||||
Self::calculate_node(¤t, neighbor, Direction::North)
|
||||
}
|
||||
|
||||
if current.last_direction != Some(Direction::West)
|
||||
&& !(current.last_direction == Some(Direction::East)
|
||||
&& current.moves_in_same_direction == Some(2))
|
||||
&& let Some(neighbor) = parsed.get_mut(current.row, current.column + 1)
|
||||
{
|
||||
// Going east
|
||||
Self::calculate_node(¤t, neighbor, Direction::East)
|
||||
}
|
||||
|
||||
if current.last_direction != Some(Direction::North)
|
||||
&& !(current.last_direction == Some(Direction::West) && current.moves_without_turn == Some(3))
|
||||
&& let Some(neighbor) = parsed.get_mut(current.x - 1, current.y)
|
||||
{ // Going west
|
||||
|
||||
&& !(current.last_direction == Some(Direction::South)
|
||||
&& current.moves_in_same_direction == Some(2))
|
||||
&& let Some(neighbor) = parsed.get_mut(current.row + 1, current.column)
|
||||
{
|
||||
// Going south
|
||||
Self::calculate_node(¤t, neighbor, Direction::South)
|
||||
}
|
||||
|
||||
if current.last_direction != Some(Direction::East)
|
||||
&& !(current.last_direction == Some(Direction::West)
|
||||
&& current.moves_in_same_direction == Some(2))
|
||||
&& let Some(neighbor) = parsed.get_mut(current.row, current.column.wrapping_sub(1))
|
||||
{
|
||||
// Going west
|
||||
Self::calculate_node(¤t, neighbor, Direction::West)
|
||||
}
|
||||
|
||||
if (current.column, current.row) == (columns - 1, rows - 1) {
|
||||
break;
|
||||
} else {
|
||||
unvisited.remove(
|
||||
unvisited
|
||||
.iter()
|
||||
.find_position(|&&coords| coords == (current.row, current.column))
|
||||
.unwrap()
|
||||
.0,
|
||||
);
|
||||
current_pos = unvisited
|
||||
.iter()
|
||||
.filter_map(|&coords| {
|
||||
parsed[coords]
|
||||
.tentative_distance
|
||||
.map(|distance| (coords.0, coords.1, distance))
|
||||
})
|
||||
.min_by_key(|x| x.2)
|
||||
.map(|(row, column, _)| (row, column))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
todo!()
|
||||
let mut path = Vec::<(usize, usize)>::new();
|
||||
let mut cursor = (columns - 1, rows - 1);
|
||||
|
||||
while let Some(prev) = parsed[cursor].prev {
|
||||
path.push(prev);
|
||||
cursor = prev;
|
||||
}
|
||||
|
||||
for (y, row_iter) in parsed.rows_iter().enumerate() {
|
||||
for (x, element) in row_iter.enumerate() {
|
||||
if !path.contains(&(x, y)) {
|
||||
print!("{}", element.cost);
|
||||
} else {
|
||||
print!("{}", match element.last_direction.as_ref() {
|
||||
Some(Direction::North) => "^",
|
||||
Some(Direction::East) => ">",
|
||||
Some(Direction::South) => "v",
|
||||
Some(Direction::West) => "<",
|
||||
_ => "+"
|
||||
}/*, element.moves_in_same_direction.unwrap_or_default() */);
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
parsed[(rows - 1, columns - 1)].tentative_distance.unwrap().to_string()
|
||||
}
|
||||
|
||||
fn part2(&mut self) -> String {
|
||||
|
|
Loading…
Reference in a new issue