added optimized versions of day16

This commit is contained in:
Ishan Jain 2024-12-17 00:54:55 +05:30
parent 09dbf0d911
commit 527b156882
2 changed files with 290 additions and 0 deletions

124
src/day16/1.rs Normal file
View File

@ -0,0 +1,124 @@
#![feature(test)]
extern crate test;
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use fxhash::FxHashMap;
const INPUTS: [&str; 2] = [
"###############
#.......#....E#
#.#.###.#.###.#
#.....#.#...#.#
#.###.#####.#.#
#.#.#.......#.#
#.#.#####.###.#
#...........#.#
###.#.#####.#.#
#...#.....#.#.#
#.#.#.###.#.#.#
#.....#...#.#.#
#.###.#.#.#.#.#
#S..#.....#...#
###############",
include_str!("./input.txt"),
];
pub fn run(input: &str) -> i64 {
let grid = input.lines().map(|x| x.chars().collect::<Vec<char>>()).collect::<Vec<Vec<char>>>();
let m = grid.len();
let n = grid[0].len();
let mut sx = 0;
let mut sy = 0;
let mut ex = 0;
let mut ey = 0;
for i in 0..m {
for j in 0..n {
if grid[i][j] == 'S' {
sx = i as i64;
sy = j as i64;
} else if grid[i][j] == 'E' {
ex = i as i64;
ey = j as i64;
}
}
}
dijkstra(&grid, (sx,sy), (ex,ey))
}
fn dijkstra(grid: &Vec<Vec<char>>, (sx, sy): (i64, i64), (ex, ey): (i64, i64)) -> i64 {
let mut best = std::i64::MAX;
let mut map = FxHashMap::default();
map.insert((sx,sy, 1), 0);
let mut heap = BinaryHeap::new();
heap.push((Reverse(0), sx, sy, 1));
while let Some((Reverse(score), x, y, dir)) = heap.pop() {
if score >= best {
continue;
}
if x == ex && y == ey {
best = std::cmp::min(best, score);
continue;
}
if grid[x as usize][y as usize] == '#' {
continue;
}
if *map.entry((x,y,dir)).or_insert(score) < score {
continue;
}
match dir {
0 => {
heap.push((Reverse(score+1), x-1, y, 0));
heap.push((Reverse(score+1001), x, y+1, 1));
heap.push((Reverse(score+1001), x, y-1, 3));
},
1 => {
heap.push((Reverse(score+1), x, y+1, 1));
heap.push((Reverse(score+1001), x+1,y, 2));
heap.push((Reverse(score+1001), x-1,y, 0));
}
2 => {
heap.push((Reverse(score+1), x+1, y, 2));
heap.push((Reverse(score+1001), x, y+1, 1));
heap.push((Reverse(score+1001), x, y-1, 3));
}
3 => {
heap.push((Reverse(score+1), x, y-1, 3));
heap.push((Reverse(score+1001), x-1, y, 0));
heap.push((Reverse(score+1001), x+1, y, 2));
}
_ => ()
}
}
best
}
fn main() {
for input in INPUTS.iter() {
println!("answer = {}", run(input));
}
}
#[bench]
fn part1(b: &mut test::Bencher) {
b.iter(|| {
let v = run(INPUTS[1]);
test::black_box(v);
});
}

166
src/day16/2.rs Normal file
View File

@ -0,0 +1,166 @@
#![feature(test)]
extern crate test;
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use fxhash::FxHashMap;
const INPUTS: [&str; 2] = [
"###############
#.......#....E#
#.#.###.#.###.#
#.....#.#...#.#
#.###.#####.#.#
#.#.#.......#.#
#.#.#####.###.#
#...........#.#
###.#.#####.#.#
#...#.....#.#.#
#.#.#.###.#.#.#
#.....#...#.#.#
#.###.#.#.#.#.#
#S..#.....#...#
###############",
include_str!("./input.txt"),
];
pub fn run(input: &str) -> i64 {
let grid = input.lines().map(|x| x.chars().collect::<Vec<char>>()).collect::<Vec<Vec<char>>>();
let m = grid.len();
let n = grid[0].len();
let mut sx = 0;
let mut sy = 0;
let mut ex = 0;
let mut ey = 0;
for i in 0..m {
for j in 0..n {
if grid[i][j] == 'S' {
sx = i as i64;
sy = j as i64;
} else if grid[i][j] == 'E' {
ex = i as i64;
ey = j as i64;
}
}
}
let visited_nodes = dijkstra(&grid, (sx,sy), (ex,ey));
visited_nodes.count() as i64
}
fn dijkstra(grid: &Vec<Vec<char>>, (sx, sy): (i64, i64), (ex, ey): (i64, i64)) -> Bitmap {
let mut best = std::i64::MAX;
let mut map = FxHashMap::default();
let mut visited = Bitmap::new(grid.len() as i64, grid[0].len() as i64);
let mut heap = BinaryHeap::new();
let path = Bitmap::new(grid.len() as i64, grid[0].len() as i64)
.set(sx,sy);
heap.push((Reverse(0), sx, sy, 1, path));
map.insert((sx,sy, 1), 0);
while let Some((Reverse(score), x, y, dir, path)) = heap.pop() {
if score > best {
continue;
}
if x == ex && y == ey {
visited.merge(path);
best = std::cmp::min(best, score);
continue;
}
if grid[x as usize][y as usize] == '#' {
continue;
}
if *map.entry((x,y,dir)).or_insert(score) < score {
continue;
}
match dir {
0 => {
heap.push((Reverse(score+1), x-1, y, 0, path.clone().set(x-1,y)));
heap.push((Reverse(score+1001), x, y+1, 1, path.clone().set(x,y+1)));
heap.push((Reverse(score+1001), x, y-1, 3, path.clone().set(x,y-1)));
},
1 => {
heap.push((Reverse(score+1), x, y+1, 1, path.clone().set(x,y+1)));
heap.push((Reverse(score+1001), x+1,y, 2, path.clone().set(x+1,y)));
heap.push((Reverse(score+1001), x-1,y, 0, path.clone().set(x-1,y)));
}
2 => {
heap.push((Reverse(score+1), x+1, y, 2, path.clone().set(x+1,y)));
heap.push((Reverse(score+1001), x, y+1, 1, path.clone().set(x,y+1)));
heap.push((Reverse(score+1001), x, y-1, 3, path.clone().set(x,y-1)));
}
3 => {
heap.push((Reverse(score+1), x, y-1, 3, path.clone().set(x,y-1)));
heap.push((Reverse(score+1001), x-1, y, 0, path.clone().set(x-1,y)));
heap.push((Reverse(score+1001), x+1, y, 2, path.clone().set(x+1,y)));
}
_ => ()
}
}
visited
}
const WORD_SIZE: usize = 64;
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd)]
struct Bitmap {
inner: Vec<u64>,
n: i64
}
impl Bitmap {
fn new(m: i64, n: i64) -> Self {
Self {
inner: vec![0; ((m * n) as usize / WORD_SIZE) + 1],
n
}
}
fn merge(&mut self, p2: Bitmap) {
for (a,b) in self.inner.iter_mut().zip(p2.inner.into_iter()) {
*a |= b;
}
}
fn set(mut self, x: i64, y: i64) -> Self {
let offset = (x * self.n + y) as usize;
let index = offset / WORD_SIZE;
let bit_offset = offset % WORD_SIZE;
self.inner[index] |= 1 << bit_offset;
self
}
fn count(self) -> u32 {
self.inner.into_iter().fold(0, |a,x| a + x.count_ones())
}
}
fn main() {
for input in INPUTS.iter() {
println!("answer = {}", run(input));
}
}
#[bench]
fn part1(b: &mut test::Bencher) {
b.iter(|| {
let v = run(INPUTS[1]);
test::black_box(v);
});
}