AOC2022/day12/src/main.rs

80 lines
2.8 KiB
Rust

use pathfinding::prelude::bfs;
use std::fs;
fn main() {
const FILE_PATH: &str = "input";
println!("Hi this is the twELFth day of AOC2022, first we will read the file {}", FILE_PATH);
let contents = fs::read_to_string(FILE_PATH)
.expect("Should have been able to read the file");
let (ini, map) = parse(&contents);
println!("The shortest path is: {}", bfs(&ini, |p| get_succs(*p, &map), |p| map[p.1][p.0] == 'E').expect("no path found").len()-1);
let mut asses = get_all_a(&map);
asses.push(ini);
let asses = asses.iter().map(|ini| bfs(ini, |p| get_succs(*p, &map), |p| map[p.1][p.0] == 'E'))
.filter(|x| x.is_some())
.map(|x| x.unwrap().len()-1);
println!("The shortestest path is: {}", asses.min().expect("Must be a lower bound"));
}
fn get_succs((px, py): (usize, usize), map: &Vec<Vec<char>>) -> Vec<(usize, usize)>{
let mut succs = Vec::new();
let (px, py) = (px as i32, py as i32);
for (x, y) in [(-1, 0), (1, 0), (0, -1), (0, 1)]{
if py+y < 0 || py+y >= map.len() as i32 || px+x < 0 || px+x >= map[0].len() as i32 {continue;}
let (px, py, pxx, pyy) = (px as usize, py as usize, (px+x) as usize, (py+y) as usize);
match map[py][px] {
'S' => if 'a' as u8+1 >= map[pyy][pxx] as u8 {succs.push((pxx, pyy))},
'E' => if 'z' as u8+1 >= map[pyy][pxx] as u8 {succs.push((pxx, pyy))},
c => if map[pyy][pxx] != 'E' && c as u8+1 >= map[pyy][pxx] as u8
|| map[pyy][pxx] == 'S'
|| (map[pyy][pxx] == 'E' && (c=='y' || c=='z'))
{succs.push((pxx, pyy))},
};
}
succs
}
fn parse(s: &str) -> ((usize, usize), Vec<Vec<char>>) {
let map: Vec<Vec<_>> = s.lines().map(|l| l.chars().collect()).collect();
let mut ini = (0, 0);
'out: for i in 0..map.len(){
for j in 0..map[i].len(){
if map[i][j] == 'S' {ini = (j,i); break 'out;}
}
};
(ini, map)
}
fn get_all_a(map: &Vec<Vec<char>>) -> Vec<(usize, usize)>{
let mut ini = Vec::new();
for i in 0..map.len(){
for j in 0..map[i].len(){
if map[i][j] == 'a' {ini.push((j,i));}
}
};
ini
}
#[cfg(test)]
mod test {
const INPUT: &str = r#"Sabqponm
abcryxxl
accszExk
acctuvwj
abdefghi"#;
use super::*;
#[test]
fn path1() {
let (ini, map) = parse(INPUT);
assert_eq!(bfs(&ini, |p| get_succs(*p, &map), |p| map[p.1][p.0] == 'E').expect("no path found").len()-1, 31);
}
#[test]
fn path2() {
let (ini, map) = parse(INPUT);
let mut asses = get_all_a(&map);
asses.push(ini);
let asses = asses.iter().map(|ini| bfs(ini, |p| get_succs(*p, &map), |p| map[p.1][p.0] == 'E').expect("no path found").len()-1);
assert_eq!(asses.min().expect("Must be a lower bound"), 29);
}
}