Compare commits

..

2 commits

Author SHA1 Message Date
Ty
70e56f94db
progress on this horrible pathfinding
it kinda works but last_direction doesn't funciton
2024-01-10 00:04:42 -07:00
Ty
9651b3a12c
Push work so far 2024-01-08 23:00:36 -07:00
7 changed files with 234 additions and 5 deletions

46
.vscode/aoc.code-snippets vendored Normal file
View file

@ -0,0 +1,46 @@
{
// Place your advent-of-code-2023 workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
// "Print to console": {
// "scope": "javascript,typescript",
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
"Day template": {
"scope": "rust",
"prefix": "day",
"body": [
"use crate::utils::Day;",
"",
"#[derive(Debug, Default)]",
"pub struct Day$1 {",
"\tpub input: String,",
"}",
"",
"impl Day for Day$1 {",
"\tfn part1(&mut self) -> String {",
"\t\t",
"\t\t",
"\t\ttodo!()",
"\t}",
"",
"\tfn part2(&mut self) -> String {",
"\t\t",
"\t\t",
"\t\ttodo!()",
"\t}",
"}"
],
"description": "Creates a template for an AOC day"
}
}

7
Cargo.lock generated
View file

@ -21,6 +21,7 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
name = "advent" name = "advent"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"array2d",
"clru", "clru",
"getrandom", "getrandom",
"itertools", "itertools",
@ -122,6 +123,12 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "array2d"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b39cb2c1bf5a7c0dd097aa95ab859cf87dab5a4328900f5388942dc1889f74"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"

View file

@ -160,7 +160,8 @@ async fn main() {
let deviation = (((max - min).pow(2) / 16) as f64).sqrt() as u128; let deviation = (((max - min).pow(2) / 16) as f64).sqrt() as u128;
let range = max - min; let range = max - min;
let median = if timings.len() % 2 == 0 { let median = if timings.len() % 2 == 0 {
(timings[timings.len()/2-1]+timings[timings.len()/2]).as_nanos() as f64 / 2.0 (timings[timings.len() / 2 - 1] + timings[timings.len() / 2]).as_nanos() as f64
/ 2.0
} else { } else {
timings[timings.len() / 2].as_nanos() as f64 timings[timings.len() / 2].as_nanos() as f64
}; };

View file

@ -12,6 +12,7 @@ scraper = "0.18.1"
reqwest = "0.11.22" reqwest = "0.11.22"
itertools = "0.12.0" itertools = "0.12.0"
clru = "0.6.1" clru = "0.6.1"
array2d = "0.3.2"
[dependencies.getrandom] [dependencies.getrandom]
version = "0.2.11" version = "0.2.11"

171
lib/src/day17/mod.rs Normal file
View file

@ -0,0 +1,171 @@
use crate::utils::Day;
use array2d::Array2D;
use itertools::Itertools;
#[derive(Debug, Default)]
pub struct Day17 {
pub input: String,
}
#[derive(PartialEq, Clone, Debug)]
pub enum Direction {
North,
East,
South,
West,
}
#[derive(Clone, Debug)]
pub struct State {
cost: usize,
row: usize,
column: usize,
tentative_distance: Option<usize>,
last_direction: Option<Direction>,
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 {
fn part1(&mut self) -> String {
let columns = self.input.find('\n').unwrap();
let rows = (self.input.len() + 1) / columns - 1;
let mut parsed = Array2D::from_iter_row_major(
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,
column: j,
row: i,
tentative_distance: None,
moves_in_same_direction: None,
last_direction: None,
prev: None
})
}),
rows,
columns,
)
.unwrap();
let mut unvisited = Vec::<(usize, usize)>::from_iter(
(0..columns).flat_map(|i| (0..rows).map(move |j| (i, j))),
);
let mut current_pos = (0usize, 0usize);
loop {
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)
&& !(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(&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();
}
}
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 {
todo!()
}
}

View file

@ -1,4 +1,4 @@
#![feature(inline_const)] #![feature(inline_const, let_chains)]
use std::{collections::HashMap, num::NonZeroUsize}; use std::{collections::HashMap, num::NonZeroUsize};
@ -11,6 +11,7 @@ use day13::Day13;
use day14::Day14; use day14::Day14;
use day15::Day15; use day15::Day15;
use day16::Day16; use day16::Day16;
use day17::Day17;
use day2::Day2; use day2::Day2;
use day3::Day3; use day3::Day3;
use day4::Day4; use day4::Day4;
@ -32,6 +33,7 @@ pub mod day13;
pub mod day14; pub mod day14;
pub mod day15; pub mod day15;
pub mod day16; pub mod day16;
pub mod day17;
pub mod day2; pub mod day2;
pub mod day3; pub mod day3;
pub mod day4; pub mod day4;
@ -79,6 +81,7 @@ pub fn get_day(day: u8, input: String) -> Box<dyn Day> {
14 => Box::new(Day14 { input }), 14 => Box::new(Day14 { input }),
15 => Box::new(Day15 { input }), 15 => Box::new(Day15 { input }),
16 => Box::new(Day16 { input }), 16 => Box::new(Day16 { input }),
17 => Box::new(Day17 { input }),
_ => panic!("Invalid day #"), _ => panic!("Invalid day #"),
} }
} }