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() {
|
||||
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 day10;
|
||||
pub mod day11;
|
||||
pub mod day12;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#![allow(dead_code)]
|
||||
use std::fmt;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::slice::{ChunksExact, Iter};
|
||||
|
||||
|
@ -111,3 +112,16 @@ impl<T> FromIterator<T> for Matrix<T> {
|
|||
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