mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Implement 2016 day 22 part 2.
Only 2 years and 2 months later.
This commit is contained in:
@@ -1,13 +1,18 @@
|
|||||||
|
use std::cmp::Reverse;
|
||||||
|
use std::collections::BinaryHeap;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::io::BufRead;
|
||||||
|
use std::io::BufReader;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use common::Solution;
|
use itertools::Itertools;
|
||||||
use std::io::BufReader;
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::io::BufRead;
|
|
||||||
|
use common::Solution;
|
||||||
|
|
||||||
type Coordinate = (usize, usize);
|
type Coordinate = (usize, usize);
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
|
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Default)]
|
||||||
struct Node {
|
struct Node {
|
||||||
pos: Coordinate,
|
pos: Coordinate,
|
||||||
capacity: usize,
|
capacity: usize,
|
||||||
@@ -20,6 +25,30 @@ impl Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_grid<T>(list: &[T], size: usize, (x, y): Coordinate) -> &T {
|
||||||
|
&list[x + size * y]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mut_grid<T>(list: &mut [T], size: usize, (x, y): Coordinate) -> &mut T {
|
||||||
|
&mut list[x + size * y]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Ord, PartialOrd, Eq, PartialEq, Clone)]
|
||||||
|
struct State {
|
||||||
|
pos: Coordinate,
|
||||||
|
empty_pos: Coordinate,
|
||||||
|
grid: Vec<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
fn estimate(&self) -> usize {
|
||||||
|
self.pos.0 + self.pos.1
|
||||||
|
+ self.pos.0.max(self.empty_pos.0) + self.pos.1.max(self.empty_pos.1)
|
||||||
|
- self.pos.0.min(self.empty_pos.0) - self.pos.1.min(self.empty_pos.1)
|
||||||
|
- 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Day22 {
|
pub struct Day22 {
|
||||||
nodes: Vec<Node>,
|
nodes: Vec<Node>,
|
||||||
@@ -49,8 +78,25 @@ impl Day22 {
|
|||||||
self.nodes.push(node)
|
self.nodes.push(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.nodes.sort_unstable();
|
||||||
|
|
||||||
assert_ne!(0, self.nodes.len())
|
assert_ne!(0, self.nodes.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_grid(&self) -> (usize, Vec<usize>, Vec<usize>) {
|
||||||
|
let size = self.nodes.iter().map(|node| node.pos.0).max().unwrap_or(0) + 1;
|
||||||
|
|
||||||
|
let mut used = vec![0usize; self.nodes.len()];
|
||||||
|
let mut capacity = used.clone();
|
||||||
|
|
||||||
|
for node in &self.nodes {
|
||||||
|
let pos = node.pos;
|
||||||
|
*get_mut_grid(&mut used, size, pos) = node.used;
|
||||||
|
*get_mut_grid(&mut capacity, size, pos) = node.capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
(size, used, capacity)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Solution for Day22 {
|
impl Solution for Day22 {
|
||||||
@@ -66,4 +112,83 @@ impl Solution for Day22 {
|
|||||||
|
|
||||||
fitting.to_string()
|
fitting.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn part2(&mut self, input: &mut Read) -> String {
|
||||||
|
self.read_input(input);
|
||||||
|
|
||||||
|
let (size, used, capacity) = self.build_grid();
|
||||||
|
|
||||||
|
let (empty_pos, _) = used.iter()
|
||||||
|
.find_position(|&&used| used == 0)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let height = used.len() / size;
|
||||||
|
|
||||||
|
let state = State {
|
||||||
|
pos: (size - 1, 0),
|
||||||
|
empty_pos: (empty_pos % size, empty_pos / size),
|
||||||
|
grid: used,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
let mut visited = HashSet::new();
|
||||||
|
visited.insert((state.pos, state.empty_pos));
|
||||||
|
|
||||||
|
let mut todo = BinaryHeap::new();
|
||||||
|
todo.push(Reverse((state.estimate(), 0usize, state)));
|
||||||
|
|
||||||
|
while let Some(Reverse((_, dist, state))) = todo.pop() {
|
||||||
|
if state.pos == (0, 0) {
|
||||||
|
return dist.to_string();
|
||||||
|
}
|
||||||
|
let (xe, ye) = state.empty_pos;
|
||||||
|
let empty_capacity = *get_grid(&capacity, size, state.empty_pos);
|
||||||
|
|
||||||
|
let valid_x = [if xe > 0 { Some(xe - 1) } else { None }, Some(xe), Some(xe), if xe < size - 1 { Some(xe + 1) } else { None }];
|
||||||
|
let valid_y = [Some(ye), if ye > 0 { Some(ye - 1) } else { None }, if ye < height - 1 { Some(ye + 1) } else { None }, Some(ye)];
|
||||||
|
for (x, y) in valid_x.iter().zip(valid_y.iter()) {
|
||||||
|
if x.is_none() || y.is_none() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
let switch = (x.unwrap(), y.unwrap());
|
||||||
|
let contents = *get_grid(&state.grid, size, switch);
|
||||||
|
|
||||||
|
if contents > empty_capacity {
|
||||||
|
// Not enough capacity
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut new_state = State {
|
||||||
|
grid: state.grid.clone(),
|
||||||
|
empty_pos: switch,
|
||||||
|
pos: if switch == state.pos { state.empty_pos } else { state.pos },
|
||||||
|
};
|
||||||
|
|
||||||
|
if !visited.contains(&(new_state.pos, new_state.empty_pos)) {
|
||||||
|
visited.insert((new_state.pos, new_state.empty_pos));
|
||||||
|
*get_mut_grid(&mut new_state.grid, size, switch) = 0;
|
||||||
|
*get_mut_grid(&mut new_state.grid, size, state.empty_pos) = contents;
|
||||||
|
|
||||||
|
todo.push(Reverse((dist + 1 + new_state.estimate(), dist + 1, new_state)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable!("Did not arrive at an end state")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use common::Solution;
|
||||||
|
use day22::Day22;
|
||||||
|
|
||||||
|
const SAMPLE_INPUT: &[u8] = include_bytes!("samples/22.txt");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part2() {
|
||||||
|
let mut instance = Day22::new();
|
||||||
|
let result = instance.part2(&mut SAMPLE_INPUT);
|
||||||
|
assert_eq!("7", result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
10
2016/src/samples/22.txt
Normal file
10
2016/src/samples/22.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Filesystem Size Used Avail Use%
|
||||||
|
/dev/grid/node-x0-y0 10T 8T 2T 80%
|
||||||
|
/dev/grid/node-x0-y1 11T 6T 5T 54%
|
||||||
|
/dev/grid/node-x0-y2 32T 28T 4T 87%
|
||||||
|
/dev/grid/node-x1-y0 9T 7T 2T 77%
|
||||||
|
/dev/grid/node-x1-y1 8T 0T 8T 0%
|
||||||
|
/dev/grid/node-x1-y2 11T 7T 4T 63%
|
||||||
|
/dev/grid/node-x2-y0 10T 6T 4T 60%
|
||||||
|
/dev/grid/node-x2-y1 9T 8T 1T 88%
|
||||||
|
/dev/grid/node-x2-y2 9T 6T 3T 66%
|
||||||
Reference in New Issue
Block a user