added optimized versions of day16
This commit is contained in:
parent
09dbf0d911
commit
527b156882
124
src/day16/1.rs
Normal file
124
src/day16/1.rs
Normal 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
166
src/day16/2.rs
Normal 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);
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user