2022 rust day 12 part 1
This commit is contained in:
parent
ae36a0e2e5
commit
88fd887d87
41
2022/rust/inputs/day12.txt
Normal file
41
2022/rust/inputs/day12.txt
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
abcccccccccaaaaaaaaaaccccccccccccaaaaaaaaccaaccccccccccccccccccccccccccccccccccccccccccccaaaaaa
|
||||||
|
abccccccccccaaaaaaaaaccccccccccccaaaaaaaaaaaacccccccccccaacccacccccccccccccccccccccccccccaaaaaa
|
||||||
|
abcccccccccccaaaaaaacccccccccccccaaaaaaaaaaaaaacccccccccaaacaacccccccccaaaccccccccccccccccaaaaa
|
||||||
|
abccccccccccaaaaaaccccccccccccccaaaaaaaaaaaaaaaccccccccccaaaaaccccccccccaaacccccccccccccccccaaa
|
||||||
|
abccccccccccaaaaaaaccccccccccccaaaaaaaaaaaaaacccccccccccaaaaaacccccccccaaaacccccccccccccccccaac
|
||||||
|
abaaccaaccccaaccaaaccccccccaaaaaaaaaaaaaaacaaccccccccccaaaaaaaacccccccccaaalcccccccccccccccaaac
|
||||||
|
abaaaaaacccccccccaaccccccccaaaaaacccaaaacccaaccccccccccaaaaaaaaccccccccalllllllcccccccccccccccc
|
||||||
|
abaaaaaacccccccaaacccccccccaaaaccccccaaaccccaaaaacccccccccaacccccccaaaakllllllllcccccccaacccccc
|
||||||
|
abaaaaaacccccccaaaacccccccccaacccccccaaaccccaaaaacccccccccaacccccccaakkklllpllllccccacaaacccccc
|
||||||
|
abaaaaaaaccccccaaaaccccaaccccccccccccccccccaaaaaaccccccccccccccccccckkkkpppppplllcccaaaaaaacccc
|
||||||
|
abaaaaaaacaaaccaaaaccaaaaaaccccccccccccccccaaaaaacccccccaaaccccckkkkkkkpppppppplllcddaaaaaacccc
|
||||||
|
abcaaaacccaacccccccccaaaaaacccccaaaccccccccaaaaaacccccccaaaaccjkkkkkkkpppppuppplmmdddddaaaccccc
|
||||||
|
abccaaaaaaaaaccccccccaaaaaaccccaaaaaacccccccaaacccccccccaaaajjjkkkkkrpppuuuuupppmmmdddddacccccc
|
||||||
|
abccccaaaaaaaacccccccaaaaacccccaaaaaacccccccccccccccccccaaacjjjjrrrrrrppuuuuupqqmmmmmddddaccccc
|
||||||
|
abccccaaaaaaaaacccccccaaaacccccaaaaaaccccccccccccccccccccccjjjrrrrrrrrpuuuxuvvqqqmmmmmddddccccc
|
||||||
|
abccccaaaaaaaaacccccccccccccccccaaaaaccccaacccaccccccccaaccjjjrrrruuuuuuuxxyvvqqqqqmmmmmdddcccc
|
||||||
|
abccccaaaaaaaacccccccccaaaccccccaacaaccccaaacaacccaaacaaaccjjjrrrtuuuuuuuxxyvvvqqqqqmmmmdddcccc
|
||||||
|
abccaaaaaaaacccccccccccaaaaaccccccccccccccaaaaacccaaaaaaaccjjjrrttttxxxxxxyyvvvvvqqqqmmmmdeeccc
|
||||||
|
abccaaaccaaaccccccccaacaaaaacccccccccccccaaaaaacccaaaaaacccjjjrrtttxxxxxxxyyvvvvvvvqqqmmmeeeccc
|
||||||
|
abaaaaaaaaaacccaaaccaaaaaaaaaaaccaaaccccaaaaaaaacccaaaaaaaajjjqqrttxxxxxxxyyyyyyvvvqqqnnneeeccc
|
||||||
|
SbaaaaaaaaccccaaaaccaaaaaaaaaaaaaaaaacccaaaaaaaaccaaaaaaaaacjjjqqtttxxxxEzzyyyyvvvvqqqnnneeeccc
|
||||||
|
abcaaaaaacccccaaaaccccaaaaaaaccaaaaaaccccccaaccccaaaaaaaaaaciiiqqqtttxxxyyyyyyvvvvrrrnnneeecccc
|
||||||
|
abcaaaaaacccccaaaacccaaaaaaaaccaaaaaaccccccaaccccaaacaaacccciiiqqqqttxxyyyyyywvvvrrrnnneeeecccc
|
||||||
|
abcaaaaaaccccccccccccaaaaaaaaacaaaaacccccccccccccccccaaaccccciiiqqtttxxyyyyyywwrrrrnnnneeeccccc
|
||||||
|
abcaaacaacccccaacccccaaaaaaaaacaaaaacccccccccccccccccaaaccccciiiqqttxxxywwyyywwrrrnnnneeecccccc
|
||||||
|
abccccccccaaacaaccccccccccacccccccccccccccccccccccccccccccccciiqqqttxxwwwwwwywwrrrnnneeeccccccc
|
||||||
|
abccaacccccaaaaaccccccccccccccccccccccccccccccccccccccccaacaaiiqqqttwwwwsswwwwwrrrnnfffeccccccc
|
||||||
|
abaaaaccccccaaaaaacccccccccccccccccccccccccccccaaaccccccaaaaaiiqqqttssssssswwwwrrronfffaccccccc
|
||||||
|
abaaaaaacccaaaaaaacccccccccccccccccccccccccccaaaaaacccccaaaaaiiqqqssssssssssswrrrooofffaaaacccc
|
||||||
|
abaaaaaaccaaaaaacccccccccccccccccccccccccccccaaaaaacccccaaaaaiiqqqppssspppssssrrrooofffaaaacccc
|
||||||
|
abaaaaaaccaacaaacccccccccccccccccccccccccccccaaaaaacccccaaaaaiihpppppppppppossrrooofffaaaaacccc
|
||||||
|
abaaaaccccccccaacccccccccccccccccccccccccccccaaaaaccccccccaaahhhhppppppppppoooooooofffaaaaccccc
|
||||||
|
abaaaaccccccccccaacccccccccccccccccaaacccccccaaaaacccccccccccchhhhhhhhhhggpoooooooffffaaaaccccc
|
||||||
|
abccaacccccccacaaaccccccccccccccccaaaaacccccccccccccccccccccccchhhhhhhhhggggoooooffffaacaaacccc
|
||||||
|
abccccccccccaaaaacaaccccccccccccccaaaaaccccccccccccccccccccccccchhhhhhhhggggggggggffcaacccccccc
|
||||||
|
abccccccccccaaaaaaaaccccccccccccccaaaacccaacccccccccccaccccccccccccccaaaaaggggggggfcccccccccccc
|
||||||
|
abccccccccccccaaaaaccccaacccccccccaaaacaaaaccccccccaaaaccccccccccccccaaaacaaagggggcccccccccaccc
|
||||||
|
abcccccccccccaaaaacccccaacccccccccaaaaaaaaaccccccccaaaaaaccccccccccccaaaccaaaacccccccccccccaaac
|
||||||
|
abcccccccccccaacaaccaaaaaaaacccaaaaaaaaaaaccccccccccaaaaccccccccccccccaccccaaacccccccccccccaaaa
|
||||||
|
abccccccccccccccaaccaaaaaaaaccaaaaaaaaaaaccccccccccaaaaacccccccccccccccccccccacccccccccccccaaaa
|
||||||
|
abccccccccccccccccccccaaaaacccaaaaaaaaaaaacccccccccaacaacccccccccccccccccccccccccccccccccaaaaaa
|
|
@ -3,5 +3,5 @@ mod solutions;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
solutions::day11::run();
|
solutions::day12::run();
|
||||||
}
|
}
|
||||||
|
|
143
2022/rust/src/solutions/day12.rs
Normal file
143
2022/rust/src/solutions/day12.rs
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::collections::{BinaryHeap, HashMap};
|
||||||
|
use crate::utils;
|
||||||
|
use crate::utils::matrix::Matrix;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn run() -> () {
|
||||||
|
let data = parse_data(&utils::read_lines(utils::Source::Day(12)));
|
||||||
|
|
||||||
|
println!("Day 12");
|
||||||
|
println!("Part 1: {}", solve1(&data));
|
||||||
|
println!("Part 2: {}", solve2(&data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Data = ((usize, usize), (usize, usize), Matrix<u8>);
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
|
struct State {
|
||||||
|
cost: i32,
|
||||||
|
position: (usize, usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for State {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
other.cost.cmp(&self.cost)
|
||||||
|
.then_with(|| self.position.cmp(&other.position))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for State {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn neighbours((row, col): (usize, usize), (rows, cols): (usize, usize)) -> Vec<(usize, usize)> {
|
||||||
|
let mut ns = Vec::with_capacity(4);
|
||||||
|
if row + 1 < rows { ns.push((row + 1, col)) };
|
||||||
|
if 0 < row { ns.push((row - 1, col)) };
|
||||||
|
if col + 1 < cols{ ns.push((row, col + 1)) };
|
||||||
|
if 0 < col { ns.push((row, col - 1)) };
|
||||||
|
ns
|
||||||
|
}
|
||||||
|
|
||||||
|
fn manhattan(start: (usize, usize), goal: (usize, usize)) -> i32 {
|
||||||
|
(start.0.abs_diff(goal.0) + start.1.abs_diff(goal.1)) as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unwind_path(
|
||||||
|
parent_map: &HashMap<(usize, usize), (usize, usize)>,
|
||||||
|
start: (usize, usize),
|
||||||
|
goal: (usize, usize),
|
||||||
|
) -> Option<Vec<(usize, usize)>> {
|
||||||
|
let mut path = vec![goal];
|
||||||
|
while !path.last()?.eq(&start) {
|
||||||
|
path.push(*parent_map.get(path.last()?)?);
|
||||||
|
}
|
||||||
|
Some(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn a_star(start: (usize, usize), goal: (usize, usize), grid: &Matrix<u8>) -> Vec<(usize, usize)> {
|
||||||
|
let mut frontier: BinaryHeap<State> = BinaryHeap::new();
|
||||||
|
let mut parent: HashMap<(usize, usize), (usize, usize)> = HashMap::new();
|
||||||
|
let mut cost: HashMap<(usize, usize), i32> = HashMap::from([(start, 0)]);
|
||||||
|
|
||||||
|
frontier.push(State { cost: 0, position: start });
|
||||||
|
while let Some(State { position: current, .. }) = frontier.pop() {
|
||||||
|
if current == goal { break };
|
||||||
|
|
||||||
|
for neighbour in neighbours(current, grid.shape()) {
|
||||||
|
// unreachable
|
||||||
|
let level_diff = grid[neighbour].abs_diff(grid[current]);
|
||||||
|
if grid[neighbour] > grid[current] && level_diff > 1 { continue };
|
||||||
|
|
||||||
|
let new_cost = cost.get(¤t).unwrap() + 1;
|
||||||
|
if !cost.contains_key(&neighbour) || new_cost < *cost.get(&neighbour).unwrap() {
|
||||||
|
cost.insert(neighbour, new_cost);
|
||||||
|
parent.insert(neighbour, current);
|
||||||
|
frontier.push(State {
|
||||||
|
cost: new_cost + manhattan(neighbour, goal),
|
||||||
|
position: neighbour,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unwind_path(&parent, start, goal).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve1((start, goal, grid): &Data) -> usize {
|
||||||
|
a_star(*start, *goal, grid).len() - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve2(data: &Data) -> i32 {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn parse_data<T: AsRef<str>>(data: &[T]) -> Data {
|
||||||
|
const OFFSET: u8 = 'a' as u8;
|
||||||
|
let mut s = (0, 0);
|
||||||
|
let mut e = (0, 0);
|
||||||
|
let map = data.iter()
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(row, line)| {
|
||||||
|
let line = line.as_ref();
|
||||||
|
line.find("S").and_then(|col| Some(s = (row, col)));
|
||||||
|
line.find("E").and_then(|col| Some(e = (row, col)));
|
||||||
|
line.chars().map(|char| match char {
|
||||||
|
'S' => 'a' as u8 - OFFSET,
|
||||||
|
'E' => 'z' as u8 - OFFSET,
|
||||||
|
c => c as u8 - OFFSET
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Matrix<_>>()
|
||||||
|
.reshape_rows(data.len());
|
||||||
|
(s, e, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
static DATA: &[&str] = &[
|
||||||
|
"Sabqponm",
|
||||||
|
"abcryxxl",
|
||||||
|
"accszExk",
|
||||||
|
"acctuvwj",
|
||||||
|
"abdefghi",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1() {
|
||||||
|
assert_eq!(31, solve1(&parse_data(DATA)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2() {
|
||||||
|
assert_eq!(2, solve2(&parse_data(DATA)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,3 +9,4 @@ pub mod day08;
|
||||||
pub mod day09;
|
pub mod day09;
|
||||||
pub mod day10;
|
pub mod day10;
|
||||||
pub mod day11;
|
pub mod day11;
|
||||||
|
pub mod day12;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
use std::fmt;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::slice::{ChunksExact, Iter};
|
use std::slice::{ChunksExact, Iter};
|
||||||
|
|
||||||
|
@ -111,3 +112,16 @@ impl<T> FromIterator<T> for Matrix<T> {
|
||||||
Matrix { array, cols, rows: 1 }
|
Matrix { array, cols, rows: 1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> fmt::Display for Matrix<T> where T: fmt::Display {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
for row in self.iter_rows() {
|
||||||
|
for item in row {
|
||||||
|
write!(f, "{}", item)?
|
||||||
|
};
|
||||||
|
write!(f, "\n")?;
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue