This commit is contained in:
Max Känner 2022-12-12 08:18:55 +01:00
parent 567877da60
commit fd3a9a2938
3 changed files with 225 additions and 2 deletions

7
day12/Cargo.lock generated Normal file
View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day12"
version = "0.1.0"

41
day12/input.txt Normal file
View File

@ -0,0 +1,41 @@
abcccccccccccccccccccccccccccccccccccccaaaaaaacccccccaaaaaaaaaaaccccccccccccccccccccaaacaaaaaaaacccccccccccccccccccccccccccccccccccaaaaa
abccccccccccccccccccaaccaacccccccccccccaaaaaaaccccccccaaaaaaaaaaacccccccaaaaccccccccaaaaaaaaaaaaacccccccccccccccccccccccccccccccccaaaaaa
abccccccccccccccccccaaaaaaccccccccccaaaccaaaaaacccccccaaaaaaaaaaccccccccaaaaccccccaaaaaaaaaaaaaaacccccccccccccccccccaaacccccccccccaaaaaa
abcccccccccccccccccccaaaaacccccccccccaaccaacaaaccccccaaaaaaaaaaaccccccccaaaacccccaaaaaaaaacaaaaaaacccccccccccccccccaaaacccccccccccaaacaa
abccccccccccccccccccaaaaaaccccccccaacaaaaaacccccccccaaaaaaaaaaaaacaaaccccaaccccccaaaaaaaaacaacccccccccccccccccaaaccaaaacccccccccccccccaa
abcccccccccccccccccaaaaaaaacccccccaaaaaaaaccccccaaaaaaaacaaaacaaaaaaacccccccccaaccccaaaaaacaaacccccccccccccccaaaakkkaaccccccccccccccccaa
abcccccccccccccccccaaaaaaaaccccccccaaaaaccccaacccaaaaaaaaaaaacaaaaaaccccccccccaacccaaaaaaaaaaaacccccccccccccccakkkkkklcccccccccccccccccc
abaaacccccccccccaaccccaaccccccccccccaaaaaccaaacccaaaaaaaaaaaaaaaaaaaaccccccaaaaaaaacaacccaaaaaaccccccccccccccckkkkkkkllcccccccaaaccccccc
abaaaacccccccaacaaccccaacccccccccccaaacaaaaaaaccccaaaaaaaaaaaaaaaaaaaacccccaaaaaaaaaaaccccaaaaacccccccccccccckkkksssllllccccccaaaaaacccc
abaaaacccccccaaaaacccccccccccaaaccccaacaaaaaaccccaaaaaacaaaaaaaaaaaaaacccccccaaaaccccccccaaaaacccccccccccccckkkksssssllllcccccaaaaaacccc
abaaacccccccccaaaaaaccccccccaaaaccccccccaaaaaaaacaaaaaaaaaaaaacaaacaaacccccccaaaaacccccccaaaaacccccccccccccjkkkrssssssllllccccccaaaccccc
abccccccccccaaaaaaaaccccccccaaaacccccccaaaaaaaaacaacaaaaaaaaaacaaaccccccccccaaacaaccccccccccccccccccccccccjjkkrrsuuussslllllcccccaaccccc
abccaaacccccaaaaacccccccccccaaaaccccccaaaaaaaaaacccccaaaaaaaaaacaaccccccccccaacccacccccccccccccccccccccjjjjjjrrrsuuuussslllllmcccddacccc
abcccaaaccaccacaaaccccccccccccccccccccaaaaaaaccccccccccaaaaaaaaccccccaacccccccccccaaaaacccccccccccccccjjjjjjrrrruuuuuusssllmmmmmddddcccc
abccaaaaaaaacccaaaccccccccccccccccaaacccccaaaccccccccccccaaacccccccccaacccccccccccaaaaacccccccccccccjjjjjrrrrrruuuxuuussqqqqmmmmmdddcccc
abcaaaaaaaacccaaaaaacaaaaaccccccaaaaaaccccaaacccaaccccccccaaccccccaaaaaaaaccaaacccaaaaaaccccccccccccjjjjrrrrrruuuxxxuuuqqqqqqqmmmdddcccc
abaaaaaaaaaccccaaaaacaaaaaccccccaaaaaaaaccccccaaaaaaccccccccccccccaaaaaaaaccaaacaaaaaaaacccccccccccjjjjrrrtttuuuuxxxyvvvvvqqqqmmmdddcccc
abaaaaaaaaaccaaaaaaacaaaaaaccccccaaaaaaaacccccaaaaaaccccccccccccccccaaaaccaaaaaaaaaaaaaacccccccccaaiijqqqrttttuuuxxyyvvvvvvvqqmmmdddcccc
abcaaaaaaaaccaaaaaaaaaaaaaacccccaaaaaaaacccccccaaaacccccaaaaccccccccaaaaacaaaaaaaaccaaccccccccccaaaiiiqqqttttxxxxxxyyyyyyvvvqqmmmdddcccc
abcccaaaaaaacaaaaaaaaaaaaaacccccaaaaaaaaaaaccccaaaaccccaaaaacccccccaaaaaacaaaaaaacccccccccccccccaaaiiiqqqtttxxxxxxxyyyyyyvvqqqmmmdddcccc
SbcccaacccaccccaaacacccaaacccccccccaaaaaaaaacccaccaccccaaaaaaccccccaaccaacccaaaaaccccccccccccccccaaiiiiqqtttxxxxEzzzyyyyvvvqqqmmmddccccc
abccaaaccccccccaaccccccccccccccccccaaaaaaaaccccccccccccaaaaaaccccccccccccccaaacaaaccaacccccccccccccciiiqqqttttxxxyyyyyvvvvqqqmmmdddccccc
abccccccccccccccccccccccccccccccccaaaaaaaccccccccccccccaaaaaacccccccccccccccaacccccaaaaaaaccccccccccciiiqqqttttxxyyyyyvvvrrrnnneeecccccc
abcaaaaccccccccccccccccccccccccccaaaaaaaaccccccccccccccccaacccccccccccccccccccccccccaaaaacccccccccccciiiqqqqttxxyyyyyyyvvrrnnnneeecccccc
abcaaaaacccccccccccccccccccccccccaaaacaaacccaccaaacccccccccccccccccccccccccaaaccccaaaaaaaccccccccccccciiiqqqttwwyywwyyywwrrnnneeeccccccc
abaaaaaacccaccaccccccccccccccccccaaaaccaacccaaaaaaccccccccccccccccaaaccccaaaaaacccaaaaaaaacccccccccccciiiqqqtswwwwwwwwwwwrrnnneeeccccccc
abaaaaaacccaaaaccccccccaaaacccccccaaacccccccaaaaaacccccccccccccccaaaaaaccaaaaaacccaaaaaaaacaaccccccaaciiiqppsswwwwsswwwwwrrrnneeeccccccc
abcaaaaacccaaaaacccccccaaaacccccccccccccccccaaaaaaaccccccccccccccaaaaaaccaaaaaacccccaaaaaaaaaccccccaaaahhpppssswwsssswwwwrrrnneeeacccccc
abcaaaccccaaaaaacccccccaaaaccccccccccccccccaaaaaaaaccccccccccccccaaaaacccaaaaaccccccaacaaaaaaaaccaaaaaahhpppsssssssssrrrrrrnnneeeacccccc
abccccccccaaaaaaccccccccaacccccccccccccccccaaaaaaaaccccaacccccccccaaaaaccaaaaacccccccccaaaaaaaaccaaaaachhpppssssssoosrrrrrrnnneeeaaacccc
abccccccccccaaccccccccccccccccaaaaaccccccaacccaaacccaaaaacccccccccaacaacccccccccccccccccaaaaaaacccaaaaahhhppppssppooooorroonnffeaaaacccc
abaaccccccccccccccccccccccccccaaaaaccccccaacccaaaccccaaaaacccccccccccccccccccccccccccaacaaaaacccccaacaahhhppppppppoooooooooonfffaaaacccc
abaccccccccccccccccccccccccccaaaaaacccaaaaaaaacccccccaaaaaccccccccccccccccccccccccaaaaaaaaaaaccccccccccchhhpppppppgggoooooooffffaacccccc
abaccccccccccccccccccccccccccaaaaaacccaaaaaaaaccccccaaaaaccccccacccaacccccccccccccaaaaaccccaaccccccccccchhhhhhggggggggfffffffffaaacccccc
abaacccccccccccccccccccccccccaaaaaacccccaaaacccccccccaaaacccaacaacaaacccccccccccccaaaaaaacccccccccccccccchhhhgggggggggffffffffccaacccccc
abcccccccaacccccccccccccccccccaaaccccccaaaaaccccccccaaaaccaaaacaaaaacccccccccccccaaaaaaaaccccccccccccccccchhhggggaaaagffffffcccccccccccc
abcccccccaacccccccccccccaacccccccccccccaaaaaaccaaccccaaaaaaaaacaaaaaacccccccaaaacaaaaaaaacccccccccccaacccccccaaaacaaaacccccccccccccccccc
abccccaaaaaaaacccccccaacaaaccccccccccccaaccaacaaaacccaaaaaaaacaaaaaaaaccccccaaaaccacaaaccaaaccccaaaaaacccccccaacccaaaacccccccccccccaaaaa
abccccaaaaaaaacccccccaaaaaccccccccccccccccccccaaaaccccaaaaaaacaaaaaaaaccccccaaaaccccaaaccaaaaaccaaaaaaaacccccccccccaaaccccccccccccccaaaa
abccccccaaaaccccccccccaaaaaaccccccccccccccccccaaaacccaaaaaaaaaaccaaccccccccccaacccccccccaaaaacccaaaaaaaacccccccccccaaaccccccccccccccaaaa
abcccccaaaaaacccccccaaaaaaaacccccccccccccccccccccccaaaaaaaaaaaaaaaacccccccccccccccccccccaaaaaacccaaaaaaaccccccccccccccccccccccccccaaaaaa

View File

@ -1,3 +1,178 @@
fn main() {
println!("Hello, world!");
use std::{collections::HashSet, fs::read_to_string};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Tile {
Start,
End,
Hight(u8),
}
impl From<char> for Tile {
fn from(input: char) -> Self {
match input {
'S' => Self::Start,
'E' => Self::End,
h => Self::Hight(('a'..='z').position(|c| c == h).unwrap() as u8),
}
}
}
impl Tile {
fn can_move_to(self, other: Tile) -> bool {
if let Self::Hight(h1) = self {
if let Self::Hight(h2) = other {
return h1 + 1 >= h2;
}
}
if self == Self::Start {
return other == Self::Hight(0) || other == Self::Hight(1);
}
if other == Self::End {
return self == Self::Hight(('a'..='z').position(|c| c == 'z').unwrap() as u8);
}
false
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
struct Map<T> {
map: Vec<T>,
width: usize,
height: usize,
}
impl From<&str> for Map<Tile> {
fn from(input: &str) -> Self {
let width = input.lines().map(|line| line.len()).next().unwrap();
let height = input.lines().count();
let map = input
.lines()
.flat_map(|line| line.chars().map(Tile::from).collect::<Vec<_>>())
.collect::<Vec<_>>();
Self { map, width, height }
}
}
impl<T> Map<T> {
fn at(&self, point: (usize, usize)) -> &T {
let (x, y) = point;
let index = x + y * self.width;
&self.map[index]
}
fn at_mut(&mut self, point: (usize, usize)) -> &mut T {
let (x, y) = point;
let index = x + y * self.width;
&mut self.map[index]
}
}
fn update(
from: (usize, usize),
to: (usize, usize),
path: &mut Map<Option<u32>>,
map: &Map<Tile>,
changed: &mut bool,
) {
if !map.at(from).can_move_to(*map.at(to)) {
return;
}
let Some(c) = path.at(from) else {return};
let cost = path.at(to);
let cost = cost.unwrap_or(u32::MAX);
if cost <= c + 1 {
return;
}
*path.at_mut(to) = Some(c + 1);
*changed = true;
}
fn find_shortest_path(map: &Map<Tile>) -> Option<u32> {
let mut path = Map {
map: vec![None; map.width * map.height],
width: map.width,
height: map.height,
};
let mut start = (0, 0);
let mut end = (0, 0);
for x in 0..map.width {
for y in 0..map.height {
match map.at((x, y)) {
Tile::Start => start = (x, y),
Tile::End => end = (x, y),
_ => (),
}
}
}
*path.at_mut(start) = Some(0);
let mut changing = true;
while changing {
changing = false;
for x in 0..map.width {
for y in 0..map.height {
let point = (x, y);
if x != 0 {
update((x - 1, y), point, &mut path, map, &mut changing);
}
if y != 0 {
update((x, y - 1), point, &mut path, map, &mut changing);
}
if x != map.width - 1 {
update((x + 1, y), point, &mut path, map, &mut changing);
}
if y != map.height - 1 {
update((x, y + 1), point, &mut path, map, &mut changing);
}
}
}
}
*path.at(end)
}
fn find_best_start(map: &Map<Tile>) -> u32 {
let mut start = (0, 0);
let mut possible_starts = HashSet::new();
for x in 0..map.width {
for y in 0..map.height {
match map.at((x, y)) {
Tile::Start => {
possible_starts.insert((x, y));
start = (x, y);
}
Tile::Hight(0) => {
possible_starts.insert((x, y));
}
_ => (),
}
}
}
let mut map = map.clone();
*map.at_mut(start) = Tile::Hight(0);
possible_starts
.iter()
.flat_map(|&start| {
let mut map = map.clone();
*map.at_mut(start) = Tile::Start;
find_shortest_path(&map)
})
.min()
.unwrap()
}
fn main() {
let input = "Sabqponm
abcryxxl
accszExk
acctuvwj
abdefghi";
let input = read_to_string("input.txt").unwrap_or_else(|_| input.to_owned());
let map: Map<_> = (&*input).into();
let cost = find_shortest_path(&map);
println!("{cost:?}");
let cost = find_best_start(&map);
println!("{cost}");
}