2022 rust day 12 part 1

This commit is contained in:
Maciej Jur 2022-12-12 16:44:12 +01:00
parent ae36a0e2e5
commit 88fd887d87
5 changed files with 200 additions and 1 deletions

View 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

View file

@ -3,5 +3,5 @@ mod solutions;
fn main() { fn main() {
solutions::day11::run(); solutions::day12::run();
} }

View 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(&current).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)));
}
}

View file

@ -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;

View file

@ -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(())
}
}