[TASK] Solved day 12

This commit is contained in:
2022-12-13 00:06:03 +01:00
parent 6518483461
commit dd05abd1a5
8 changed files with 240 additions and 57 deletions

View File

@@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run-aoc2022-bench-dayX" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="command" value="run --package advent-of-code-2022-rust --bin advent-of-code-2022-rust --release -- -d 4 -b 1000" />
<option name="command" value="run --package advent-of-code-2022-rust --bin advent-of-code-2022-rust --release -- -d 12 -b 100" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<option name="channel" value="DEFAULT" />
<option name="requiredFeatures" value="true" />

19
.run/run-day-12.run.xml Normal file
View File

@@ -0,0 +1,19 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="run-day-12" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="command" value="run --package advent-of-code-2022-rust --bin advent-of-code-2022-rust -- -d 12" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<option name="channel" value="DEFAULT" />
<option name="requiredFeatures" value="true" />
<option name="allFeatures" value="false" />
<option name="emulateTerminal" value="false" />
<option name="withSudo" value="false" />
<option name="buildTarget" value="REMOTE" />
<option name="backtrace" value="SHORT" />
<envs />
<option name="isRedirectInput" value="false" />
<option name="redirectInputPath" value="" />
<method v="2">
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method>
</configuration>
</component>

41
input/day12.txt Normal file
View File

@@ -0,0 +1,41 @@
abccccaaaaaaacccaaaaaaaccccccccccccccccccccccccccccccccccaaaa
abcccccaaaaaacccaaaaaaaaaaccccccccccccccccccccccccccccccaaaaa
abccaaaaaaaaccaaaaaaaaaaaaaccccccccccccccccccccccccccccaaaaaa
abccaaaaaaaaaaaaaaaaaaaaaaacccccccccaaaccccacccccccccccaaacaa
abaccaaaaaaaaaaaaaaaaaacacacccccccccaaacccaaaccccccccccccccaa
abaccccaaaaaaaaaaaaaaaacccccccccccccaaaaaaaaaccccccccccccccaa
abaccccaacccccccccaaaaaacccccccccccccaaaaaaaacccccccccccccccc
abcccccaaaacccccccaaaaaaccccccccijjjjjjaaaaaccccccaaccaaccccc
abccccccaaaaacccccaaaacccccccciiijjjjjjjjjkkkkkkccaaaaaaccccc
abcccccaaaaacccccccccccccccccciiiirrrjjjjjkkkkkkkkaaaaaaccccc
abcccccaaaaaccccccccccccccccciiiirrrrrrjjjkkkkkkkkkaaaaaccccc
abaaccacaaaaacccccccccccccccciiiqrrrrrrrrrrssssskkkkaaaaacccc
abaaaaacaaccccccccccccccccccciiiqqrtuurrrrrsssssskklaaaaacccc
abaaaaacccccccccccaaccccccccciiqqqttuuuurrssusssslllaaccccccc
abaaaaaccccccccaaaaccccccccciiiqqqttuuuuuuuuuuusslllaaccccccc
abaaaaaacccccccaaaaaaccccccciiiqqqttxxxuuuuuuuusslllccccccccc
abaaaaaaccccaaccaaaaacccccchhiiqqtttxxxxuyyyyvvsslllccccccccc
abaaacacccccaacaaaaaccccccchhhqqqqttxxxxxyyyyvvsslllccccccccc
abaaacccccccaaaaaaaacccccchhhqqqqtttxxxxxyyyvvssqlllccccccccc
abacccccaaaaaaaaaaccaaacchhhpqqqtttxxxxxyyyyvvqqqlllccccccccc
SbaaacaaaaaaaaaaaacaaaaahhhhppttttxxEzzzzyyvvvqqqqlllcccccccc
abaaaaaaacaaaaaacccaaaaahhhppptttxxxxxyyyyyyyvvqqqlllcccccccc
abaaaaaaccaaaaaaaccaaaaahhhppptttxxxxywyyyyyyvvvqqqmmcccccccc
abaaaaaaacaaaaaaacccaaaahhhpppsssxxwwwyyyyyyvvvvqqqmmmccccccc
abaaaaaaaaaaaaaaacccaacahhhpppssssssswyyywwvvvvvqqqmmmccccccc
abaaaaaaaacacaaaacccccccgggppppsssssswwywwwwvvvqqqqmmmccccccc
abcaaacaaaccccaaaccccccccgggppppppssswwwwwrrrrrqqqmmmmccccccc
abcaaacccccccccccccccccccgggggpppoosswwwwwrrrrrqqmmmmddcccccc
abccaacccccccccccccccccccccgggggoooosswwwrrrnnnmmmmmddddccccc
abccccccccccccccccccccccccccgggggooossrrrrrnnnnnmmmddddaccccc
abaccccaacccccccccccccccccccccgggfoossrrrrnnnnndddddddaaacccc
abaccaaaaaaccccccccccccccccccccgffooorrrrnnnneeddddddaaaacccc
abaccaaaaaacccccccccccccccccccccfffooooonnnneeeddddaaaacccccc
abacccaaaaaccccccccaaccaaaccccccffffoooonnneeeeccaaaaaacccccc
abcccaaaaacccccccccaaccaaaaccccccffffoooneeeeeaccccccaacccccc
abaccaaaaaccccccccaaaacaaaaccccccafffffeeeeeaaacccccccccccccc
abacccccccccccccccaaaacaaacccccccccffffeeeecccccccccccccccaac
abaaaacccccccaaaaaaaaaaaaaacccccccccfffeeeccccccccccccccccaaa
abaaaacccccccaaaaaaaaaaaaaaccccccccccccaacccccccccccccccccaaa
abaacccccccccaaaaaaaaaaaaaaccccccccccccaacccccccccccccccaaaaa
abaaaccccccccccaaaaaaaaccccccccccccccccccccccccccccccccaaaaaa

5
input/day12_example.txt Normal file
View File

@@ -0,0 +1,5 @@
Sabqponm
abcryxxl
accszExk
acctuvwj
abdefghi

113
src/day12.rs Normal file
View File

@@ -0,0 +1,113 @@
use crate::day_solver::DaySolver;
use crate::util::Grid;
use super::util;
pub struct Day12 {
map: Grid<u8>,
start: (usize, usize),
end: (usize, usize)
}
impl Day12 {
pub fn create() -> Self {
// let lines = util::read_file("input/day12_example.txt");
let lines = util::read_file("input/day12.txt");
let map_1d = lines.join("");
let width = lines[0].len();
let s_idx = map_1d.find("S").unwrap();
let e_idx = map_1d.find("E").unwrap();
// Put the input into the day struct
return Day12 {
map: Grid {
width,
data: map_1d.chars().map(|c| match c {
'S' => 0u8,
'E' => 'z' as u8 - 'a' as u8,
_ => c as u8 - 'a' as u8
})
.collect()
},
start: (s_idx % width, s_idx / width),
end: (e_idx % width, e_idx / width)
}
}
fn can_reach(&self, from: &u8, to: &u8) -> bool {
to < from || to - from <= 1
}
fn try_add_path_to_neighbor(&self, cur_pos: usize, target_pos: usize, dists: &mut Vec<usize>, positions_to_check: &mut Vec<usize>, prev_idx: &mut Vec<Option<usize>>) {
let cur_dist = dists[cur_pos];
let cur_height = self.map.data[cur_pos];
if self.can_reach(&cur_height, &self.map.data[target_pos]) && dists[target_pos] > cur_dist + 1 {
dists[target_pos] = cur_dist + 1;
positions_to_check.push(target_pos);
prev_idx[target_pos] = Some(cur_pos);
}
}
fn calculate_distance_to_end(&self, starting_positions: Vec<usize>) -> usize {
let mut dists = vec![usize::MAX; self.map.data.len()];
let mut prev_idx: Vec<Option<usize>> = vec![None; self.map.data.len()];
for start_idx in &starting_positions {
dists[*start_idx] = 0;
}
let mut positions_to_check = starting_positions.to_owned();
while !positions_to_check.is_empty() {
positions_to_check.sort_by_key(|p| usize::MAX - dists[*p]);
let cur_pos = positions_to_check.pop().unwrap();
// Check for each neighbor, if it's accessible, and if moving from here to the neighbor is shorter
// move up
if cur_pos >= self.map.width {
let up_pos = cur_pos - self.map.width;
self.try_add_path_to_neighbor(cur_pos, up_pos, &mut dists, &mut positions_to_check, &mut prev_idx);
}
// move down
if cur_pos + self.map.width < self.map.data.len() {
let down_pos = cur_pos +self.map.width;
self.try_add_path_to_neighbor(cur_pos, down_pos, &mut dists, &mut positions_to_check, &mut prev_idx);
}
// move left
if cur_pos % self.map.width > 0 {
let left_pos = cur_pos - 1;
self.try_add_path_to_neighbor(cur_pos, left_pos, &mut dists, &mut positions_to_check, &mut prev_idx);
}
// move right
if cur_pos % self.map.width < self.map.width - 1 {
let right_pos = cur_pos + 1;
self.try_add_path_to_neighbor(cur_pos, right_pos, &mut dists, &mut positions_to_check, &mut prev_idx);
}
}
// println!("{:?}", dists);
let end_idx = self.end.0 + self.end.1 * self.map.width;
return dists[end_idx]
}
}
impl DaySolver for Day12 {
fn solve_part1(&mut self) -> String {
let start_idx = self.start.0 + self.start.1 * self.map.width;
self.calculate_distance_to_end(vec![start_idx]).to_string()
}
fn solve_part2(&mut self) -> String {
self.calculate_distance_to_end(self.map.data.iter().enumerate().filter(|(i, x)| x == &&0).map(|(i, _)| i).collect()).to_string()
}
}

View File

@@ -1,63 +1,10 @@
use std::{fmt::{Debug, Display}};
use std::fmt::Debug;
use crate::day_solver::DaySolver;
use crate::util::Grid;
use super::util;
#[derive(Debug, Clone)]
pub struct Grid<T> {
width: usize,
data: Vec<T>
}
impl<T: Clone + Sized> Grid<T> {
#[allow(dead_code)]
fn set_row(&mut self, x: usize, v: T) {
// let range = &mut self.data[x * self.width..(x+1) * self.width];
for i in self.width * x..self.width * (x + 1) {
self.data[i] = v.to_owned();
}
}
#[allow(dead_code)]
fn set_col(&mut self, x: usize, v: T) {
for y in 0..self.height() {
let idx = self.idx(&x, &y);
self.data[idx] = v.to_owned();
}
}
fn idx(&self, x: &usize, y: &usize) -> usize {
y * self.width + x
}
fn height(&self) -> usize {
self.data.len() / self.width
}
fn get(&self, x: &usize, y: &usize) -> &T {
let idx = self.idx(x, y);
&self.data[idx]
}
}
impl <T: Display + Clone + Sized> Grid<T> {
#[allow(dead_code)]
fn print(&self) {
for y in 0..self.height() {
for x in 0..self.width {
print!("{}", self.get(&x, &y))
}
println!();
}
}
}
#[derive(Debug, Clone)]
pub struct Day8 {
grid: Grid<u8>

View File

@@ -10,6 +10,7 @@ use crate::day8::Day8;
use crate::day9::Day9;
use crate::day10::Day10;
use crate::day11::Day11;
use crate::day12::Day12;
use crate::day_solver::DaySolver;
mod util;
@@ -25,8 +26,9 @@ mod day8;
mod day9;
mod day10;
mod day11;
mod day12;
const MAX_DAY: u8 = 11;
const MAX_DAY: u8 = 12;
const DEFAULT_BENCHMARK_AMOUNT: u32 = 100;
fn main() {
@@ -101,6 +103,7 @@ fn build_day_solver(day: u8) -> Option<Box<dyn DaySolver>> {
9 => Some(Box::new(Day9::create())),
10 => Some(Box::new(Day10::create())),
11 => Some(Box::new(Day11::create())),
12 => Some(Box::new(Day12::create())),
_ => None
}
}

View File

@@ -1,3 +1,4 @@
use std::fmt::Display;
use std::fs;
pub fn read_file(filename: &str) -> Vec<String> {
@@ -10,4 +11,58 @@ pub fn read_file(filename: &str) -> Vec<String> {
res
}
#[derive(Debug, Clone)]
pub struct Grid<T> {
pub(crate) width: usize,
pub(crate) data: Vec<T>
}
impl<T: Clone + Sized> Grid<T> {
#[allow(dead_code)]
fn set_row(&mut self, x: usize, v: T) {
// let range = &mut self.data[x * self.width..(x+1) * self.width];
for i in self.width * x..self.width * (x + 1) {
self.data[i] = v.to_owned();
}
}
#[allow(dead_code)]
fn set_col(&mut self, x: usize, v: T) {
for y in 0..self.height() {
let idx = self.idx(&x, &y);
self.data[idx] = v.to_owned();
}
}
pub(crate) fn idx(&self, x: &usize, y: &usize) -> usize {
y * self.width + x
}
pub(crate) fn height(&self) -> usize {
self.data.len() / self.width
}
pub(crate) fn get(&self, x: &usize, y: &usize) -> &T {
let idx = self.idx(x, y);
&self.data[idx]
}
}
impl <T: Display + Clone + Sized> Grid<T> {
#[allow(dead_code)]
fn print(&self) {
for y in 0..self.height() {
for x in 0..self.width {
print!("{}", self.get(&x, &y))
}
println!();
}
}
}