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