2022 day 24 part 1

This commit is contained in:
Maciej Jur 2022-12-24 11:33:58 +01:00
parent 09303e8b5c
commit cc4ccca943
3 changed files with 103 additions and 22 deletions

View file

@ -0,0 +1,27 @@
#.########################################################################################################################
#>v<^v>v^.^>v<v.^<.^v>^v^<^v^^v.><^v^v<><>><^>^>>>vv..>.^<<>><^<v>^vv<>^v<v>v>.<><<<><>>v..v<^^vv^^vv.^v^^>^^^.^v^vv<<^v.#
#><^vvv^^vv>v>^<^v^^<^<v<<v><.^<^v><>>^>^^^.>^v>>..<<>>^>><^^v<^<<^^>^><<>vvv^.>^v<v>v^>^>vv>vv>.><<>^<v><^.>vv.<<.^^v<<<#
#<^v<v^<v<>>v>v^>^<.>^^vv<^^vv^v>^><^^^^<v<^>^<vv<>.^<>>><><>^>>^><^<.v<>v<.v>.>v<^^v<vv.<vv<<>v.<<<^^^>>^<v^v>^>v<.^vv^>#
#>^<<.>^<>>v.>^..v<><v>^v<vv>v^v>>^v>v.>.v>vvv.v.><v.>^^><vv>><<>>v>.v>.>^>^<>^<<<^>^v^v^.^v^v>>><>v^^^><><v<>>v>.^<^.vv<#
#..><.>v<^v<<v>.^^<^>^v<><<>.>>v<^<><>v^<.<<^>v^.>v^<^>vv^<<^>^.>..>.<<<<^<v<<><<<^>>^<<>v>^^^<^^<>^^><^.<><v<<v^^<<v<v<<#
#<^.<v>vv>^.v.^^^.^v<<.^>>><<.<>.<v^^<.v^vv>^^<vvv^>v<>^<^v<v><<^>vvv>.^>^<^^>v<v^>v^<v<^^..>^>>^.<>>>vv<<<.v>^<<vv<v><>>#
#>v<.v^>^^v..>>.^>.>>v><><><<v>^>^>>.>v<vv^<v^v<>><v>><<.>.<><v^.^<>.v^^>v^><<><>^>^<><v<>v^>v>^^>^><<.>>v<>v.<^v^^..v<v<#
#>.>.^.<^v>v^v.>>><v^v.v>.><^>>>^>vv.<v^.^v<vv.<.^<>^<.^v>v<.><>^<v<v<<v<<.^<v<>>>>>.<v.v<><<>><>^<.<.^>><>^^.>.>^^v>.^<<#
#>v><<<>v>.>.^>><<v><^<<v^>.^^^<.<>.>vv>.>v.^><v<>v<v^>>^v>.v^^.vv^^<>v<><^^<^><^.^^>^v<vv^>>>>^^<.<v<^<>>.><<v^.v.<..<<>#
#<<<vv>>v>>>^<<v<<v><<>^.v>v<v><vv^>^><>^<^^.<>>>><><>^>v^<^vv^>^.<.v<^v.>>>^v.v>>>v<^^>>.>^v>.vv>><<>v^<v>>.v^<><v<v<>v<#
#>^<vv<v^v<^.v>>><<v<v.vv<v>^<.>>>>.>.v.>vvv^^^v^<v^v^<><>^<><^>.>^.v^>.<^v<^v>^..v^^>><.^^>.vv>>>>vvv.^<>>v<>>v>vv^v<>><#
#>^^>v^^>..<.>^<v<^v..<v>^<v.v><.<v^.>>v<.><^<>>.<<<^<vv<.<v>v<>v>^<.^^>^<v<><>>v.>v^v>.<>vv<>.v^>v.v>>><<vv>.>v>v^v<>>v<#
#<^v.v>>^^^<^^<^>><>^>><<><<v<<>^.<<v><v.<^>^v<.><v<<.<>^^>v<^^^^.>>^v.><..>.>v><>^>v.v>^v<^v.vv<><><<^v^vv<<^<^>^<.<<>>.#
#>^v<^^v>vv^.^.>>.v>>.^.^.v^>^><>v>>^>>.v.vvvv.v<v.>v><<<>vv>v<<<^<>.^^.<<..v>^^<<^^<<>><>>v^^v.<<>v^^<^^v>>v><^v^<<<v^^<#
#>>.>>><v>>^.v>^^^<..^>>>>.><^^^<^^>>^>vv>^<^<<v^^v.v^><^<<<<>>>.v^<.^^^^<<v>.v^^^v<<^v<^^<^v<<v>^>.^<<<>>^<.<<<v<.<><^^>#
#<v>v^.v>><v<><v>><.<<>^.v<<<^<vv^<^<>^<.^^>>v>>v<^^<v>^<.>vv..<v^<>>^>>><.v^v^v^<>^>vvv<v^><v.>><v^v^<^^^.vv>vvv.^>>.^^<#
#><v<.^><<.^>>^><<>>>v<>v^>^^^<^><>^>>^v^^^<.>>^vv<^v><>>^<>^^^>^>^>v^vv^<>.^.^^v^.vv^^^>^v>^v.>^>v><<^.v^.<>v^>^^v<><v><#
#>v>^..<^^>^<^^^<v>^.vv<^v<^<..^^>v^>^^^>.v><..>vv<vv^^^^v..<v<^vvv^<v.v<v^>v<<<v^.^<.>^.^<^v<<<<>^v^>.vv^<<<<>^v><>>><v>#
#>>>><<><<<>vvv^<v>>^>..v<vvv<v<>^<<<<vvv^v^v<<vv>><.>><<><^vv<v.>vv<<>><^>^>.>v>v^v>.<^vvv><vvv^<v<<.^v>..v>v<<^><>v>>^>#
#<v>>^v<<^^vv<vv^^^v>^>v^><^^^^>v^v^>>.>vv<>v>^<<v<<^v<><<v<>vvv>v^^^^<^^.v>>><^v>v^<^<><^v>><<^<<^<^.vv<^<<v.<<v^<><><>>#
#><^>>vv<<^v<<^^<><>>^^>><><^>><<^<v^v.^<<^v>>.vv^><v.v.v<<v><>>v>v^>>vvv>>v..>^<.^<.v.<<^>>^<v^<^v>^>v>>.><v>^<v.v<>v<<<#
#><<<^.v^^>.v>>v>>^<>v>>>..^v>.^<>^v..vv^<<v<.^v^<^v<^v>>^..^<^^<v^^v<>.v<vv<^v^vv<>v<<>.^.<<^v^<^>>v^>^v<><>.>v^^vv><^^>#
#<<v.>.^v^<<v^v^.^<<<v^>^v<<^<>^>.v<v><<v<v>^>>vv<^v<.<>^^>><>.>vv^>>^<<v>.>>v^v.vvvv<^v.^>><<<v^.<.><><>>^><^v>v<>>^^>v<#
#>>.^<.^>^.<^<.<<<><v^><<v<<<..<vv><<v..><v^v.>v<..^^<.v^<>^>^<v><<vv^v.>><<v^<>^<<^.>>vv<vv<>><<<^^v>^>v.<<<^^.>>.^v>>>>#
#>^<v^<><v^>.^<<<<..<v<>^>>.v<<<^.v>^<<<>>.^.^><>>v>^>>v^v<<<^^<v>><v><>>>.>>^>^.v.><^^^vv<^<><^<.vv><<vv<<><^<.>>vv^vv><#
########################################################################################################################.#

View file

@ -25,5 +25,6 @@ fn main() {
// solutions::day20::run();
// solutions::day21::run();
// solutions::day22::run();
solutions::day23::run();
// solutions::day23::run();
solutions::day24::run();
}

View file

@ -1,4 +1,5 @@
use std::collections::HashSet;
use std::cmp::Ordering;
use std::collections::{BinaryHeap, HashMap, HashSet};
use crate::utils;
@ -11,6 +12,8 @@ pub fn run() -> () {
}
type Pos = (isize, isize);
#[derive(Copy, Clone, Debug)]
enum Dir {
U, D, L, R
@ -19,11 +22,11 @@ enum Dir {
#[derive(Copy, Clone, Debug)]
struct Blizzard {
dir: Dir,
pos: (isize, isize),
pos: Pos,
}
fn offset_blizzards(blizzards: &[Blizzard], (rows, cols): (isize, isize), offset: isize) -> HashSet<(isize, isize)> {
fn offset_blizzards(blizzards: &[Blizzard], (rows, cols): (isize, isize), offset: isize) -> HashSet<Pos> {
blizzards.iter()
.map(|&Blizzard { dir, pos: (row, col) }| match dir {
Dir::U => ((row - offset).rem_euclid(rows), col),
@ -35,10 +38,62 @@ fn offset_blizzards(blizzards: &[Blizzard], (rows, cols): (isize, isize), offset
}
fn solve1((dims, blizzards): &((isize, isize), Vec<Blizzard>)) -> i32 {
let o = offset_blizzards(blizzards, *dims, 5);
println!("{o:?}");
1
#[derive(Copy, Clone, Eq, PartialEq)]
struct State {
cost: isize,
position: (isize, Pos),
}
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): Pos, (rows, cols): (isize, isize)) -> impl Iterator<Item=Pos> {
[(row, col), (row+1, col), (row-1, col), (row, col+1), (row, col-1)].into_iter().filter(move |&(n_row, n_col)|
0 <= n_row && (n_row < rows || n_col == cols - 1) && 0 <= n_col && n_col < cols)
}
fn manhattan(start: Pos, goal: Pos) -> isize {
(start.0.abs_diff(goal.0) + start.1.abs_diff(goal.1)) as isize
}
fn a_star(start: Pos, goal: Pos, dims: (isize, isize), blizzards: &[Blizzard]) -> Option<isize> {
let mut frontier: BinaryHeap<State> = BinaryHeap::new();
let mut parent: HashMap<(isize, Pos), (isize, Pos)> = HashMap::new();
let mut cost: HashMap<(isize, Pos), isize> = HashMap::from([((0, start), 0)]);
frontier.push(State { cost: 0, position: (0, start) });
while let Some(State { position: (cur_t, cur_pos), .. }) = frontier.pop() {
if cur_pos == goal { return Some(cur_t) };
let next_t = cur_t + 1;
let blizzards = offset_blizzards(blizzards, dims, next_t);
for neighbour in neighbours(cur_pos, dims).filter(|p| !blizzards.contains(p)) {
let new_cost = cost.get(&(cur_t, cur_pos)).unwrap() + 1;
if !cost.contains_key(&(next_t, neighbour)) || new_cost < cost[&(next_t, neighbour)] {
cost.insert((next_t, neighbour), new_cost);
parent.insert((next_t, neighbour), (cur_t, cur_pos));
frontier.push(State {
cost: new_cost + manhattan(neighbour, goal),
position: (next_t, neighbour),
});
}
}
}
None
}
fn solve1((dims, blizzards): &((isize, isize), Vec<Blizzard>)) -> isize {
let (start, goal) = ((-1_isize, 0_isize), (dims.0, dims.1 - 1));
a_star(start, goal, *dims, blizzards).unwrap()
}
fn solve2(data: &((isize, isize), Vec<Blizzard>)) -> i32 {
@ -52,9 +107,10 @@ fn parse_data<T: AsRef<str>>(data: &[T]) -> ((isize, isize), Vec<Blizzard>) {
let blizzards = data.iter()
.skip(1)
.enumerate()
.flat_map(|(row, line)| {
let line = line.as_ref();
line.chars().skip(1).enumerate().filter_map(move |(col, char)| {
.flat_map(|(row, line)| line.as_ref().chars()
.skip(1)
.enumerate()
.filter_map(move |(col, char)| {
let pos = (row as isize, col as isize);
match char {
'^' => Some(Blizzard { dir: Dir::U, pos }),
@ -62,9 +118,7 @@ fn parse_data<T: AsRef<str>>(data: &[T]) -> ((isize, isize), Vec<Blizzard>) {
'<' => Some(Blizzard { dir: Dir::L, pos }),
'>' => Some(Blizzard { dir: Dir::R, pos }),
_ => None,
}
})
})
}}))
.collect();
((rows, cols), blizzards)
}
@ -75,19 +129,18 @@ mod tests {
use super::*;
static DATA: &[&str] = &[
"#.#####",
"#.....#",
"#>....#",
"#.....#",
"#...v.#",
"#.....#",
"#####.#",
"#.######",
"#>>.<^<#",
"#.<..<<#",
"#>v.><>#",
"#<^v^^>#",
"######.#",
];
#[test]
fn part1() {
let data = parse_data(DATA);
assert_eq!(1, solve1(&data));
assert_eq!(18, solve1(&data));
}
#[test]