progress on this horrible pathfinding

it kinda works but last_direction doesn't funciton
This commit is contained in:
Tyler Beckman 2024-01-10 00:04:42 -07:00
parent 9651b3a12c
commit 70e56f94db
Signed by: Ty
GPG key ID: 2813440C772555A4

View file

@ -1,12 +1,13 @@
use crate::utils::Day; use crate::utils::Day;
use array2d::Array2D; use array2d::Array2D;
use itertools::Itertools;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Day17 { pub struct Day17 {
pub input: String, pub input: String,
} }
#[derive(PartialEq)] #[derive(PartialEq, Clone, Debug)]
pub enum Direction { pub enum Direction {
North, North,
East, East,
@ -14,13 +15,38 @@ pub enum Direction {
West, West,
} }
#[derive(Clone, Debug)]
pub struct State { pub struct State {
cost: usize, cost: usize,
x: usize, row: usize,
y: usize, column: usize,
tentative_distance: Option<usize>, tentative_distance: Option<usize>,
last_direction: Option<Direction>, 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 { impl Day for Day17 {
@ -32,46 +58,111 @@ impl Day for Day17 {
self.input.split('\n').enumerate().flat_map(|(i, str)| { self.input.split('\n').enumerate().flat_map(|(i, str)| {
str.chars().enumerate().map(move |(j, b)| State { str.chars().enumerate().map(move |(j, b)| State {
cost: b.to_digit(10).unwrap() as usize, cost: b.to_digit(10).unwrap() as usize,
x: i, column: j,
y: j, row: i,
tentative_distance: if i == 0 && j == 0 { tentative_distance: None,
Some(b.to_digit(10).unwrap() as usize) moves_in_same_direction: None,
} else { last_direction: None,
None prev: 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
},
}) })
}), }),
rows, rows,
columns, columns,
) )
.unwrap(); .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))), (0..columns).flat_map(|i| (0..rows).map(move |j| (i, j))),
); );
let mut current = (0usize, 0usize); let mut current_pos = (0usize, 0usize);
loop { 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(&current, 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(&current, neighbor, Direction::East)
}
if current.last_direction != Some(Direction::North) if current.last_direction != Some(Direction::North)
&& !(current.last_direction == Some(Direction::West) && current.moves_without_turn == Some(3)) && !(current.last_direction == Some(Direction::South)
&& let Some(neighbor) = parsed.get_mut(current.x - 1, current.y) && current.moves_in_same_direction == Some(2))
{ // Going west && let Some(neighbor) = parsed.get_mut(current.row + 1, current.column)
{
// Going south
Self::calculate_node(&current, 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(&current, 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 { fn part2(&mut self) -> String {