Implement day 22.

This commit is contained in:
2018-12-22 08:15:53 +01:00
parent fb3196f95a
commit 655ce5af18
2 changed files with 162 additions and 6 deletions

View File

@@ -1,7 +1,34 @@
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 common::Solution;
type Coordinate = (usize, usize);
#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Copy, Clone, Debug)]
struct State {
pos: Coordinate,
climbing: bool,
torch: bool,
}
impl State {
pub fn is_valid(&self, terrain: usize) -> bool {
match terrain {
0 => self.torch || self.climbing,
1 => !self.torch,
2 => !self.climbing,
_ => panic!(),
}
}
}
const MOD_BASE: usize = 20183;
#[derive(Default)] #[derive(Default)]
pub struct Day22 {} pub struct Day22 {}
@@ -11,15 +38,142 @@ impl Day22 {
} }
} }
impl Solution for Day22 { fn compute_table((x, y): Coordinate, depth: usize) -> Vec<Vec<usize>> {
fn part1(&mut self, _input: &mut Read) -> String { let mut table = vec![vec![0usize; x + 1]; y + 1];
unimplemented!() table[0][0] = 0;
for x in 1..=x {
table[0][x] = (16807 * x + depth) % MOD_BASE;
} }
fn part2(&mut self, _input: &mut Read) -> String { for y in 1..=y {
unimplemented!() table[y][0] = (48271 * y + depth) % MOD_BASE;
}
for y in 1..=y {
for x in 1..=x {
table[y][x] = (table[y - 1][x] * table[y][x - 1] + depth) % MOD_BASE;
}
}
for c in table.iter_mut().flat_map(|x| x.iter_mut()) {
*c %= 3;
}
table
}
fn read_input(input: &mut Read) -> (usize, Coordinate) {
let mut buf = String::new();
let mut reader = BufReader::new(input);
reader.read_line(&mut buf).unwrap();
let depth: usize;
{
let mut parts = buf.trim().split(' ');
depth = parts.nth(1).unwrap().parse().unwrap();
}
buf.clear();
reader.read_line(&mut buf).unwrap();
let target: Coordinate;
{
let mut parts = buf.trim().split(|c| c == ',' || c == ' ');
let x: usize = parts.nth(1).unwrap().parse().unwrap();
let y: usize = parts.next().unwrap().parse().unwrap();
target = (x, y);
}
(depth, target)
}
impl Solution for Day22 {
fn part1(&mut self, input: &mut Read) -> String {
let (depth, target) = read_input(input);
let mut table = compute_table(target, depth);
table[target.1][target.0] = 0;
let result: usize = table.iter().flat_map(|x| x.iter())
.sum();
format!("{}", result)
}
fn part2(&mut self, input: &mut Read) -> String {
let (depth, target) = read_input(input);
let mut table = compute_table((1000, 1000), depth);
table[target.1][target.0] = 0;
let mut todo = BinaryHeap::new();
let mut visited: HashSet<State> = HashSet::new();
todo.push((Reverse(0), State { pos: (0, 0), climbing: false, torch: true }));
let target_state = State { pos: target, climbing: false, torch: true };
while let Some((Reverse(dist), state)) = todo.pop() {
if visited.contains(&state) {
continue;
}
visited.insert(state);
if state == target_state {
return format!("{}", dist);
}
let (x, y) = state.pos;
// Handle equipment changes
let changes = [
State { pos: state.pos, climbing: state.climbing, torch: !state.torch },
State { pos: state.pos, climbing: !state.climbing, torch: state.torch },
State { pos: state.pos, climbing: !state.climbing, torch: !state.torch },
];
for state in changes.iter().cloned() {
if visited.contains(&state) || !state.is_valid(table[y][x]) {
continue;
}
todo.push((Reverse(dist + 7), state));
}
let xmin = if x == 0 { 0 } else { x - 1 };
let ymin = if y == 0 { 0 } else { y - 1 };
for xn in xmin..=(x + 1) {
for yn in ymin..=(y + 1) {
let new_state = State {
pos: (xn, yn),
torch: state.torch,
climbing: state.climbing,
};
if !visited.contains(&new_state) && new_state.is_valid(table[yn][xn]) && (x == xn || y == yn) {
todo.push((Reverse(dist + 1), new_state));
}
}
}
//println!("{} {:?} {:?}", dist, &state, &todo);
}
unreachable!();
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests {} mod tests {
use common::Solution;
use super::*;
const SAMPLE_INPUT: &[u8] = include_bytes!("samples/22.txt");
#[test]
fn sample_part1() {
let mut instance = Day22::new();
assert_eq!("114", instance.part1(&mut SAMPLE_INPUT));
}
#[test]
fn sample_part2() {
let mut instance = Day22::new();
assert_eq!("45", instance.part2(&mut SAMPLE_INPUT));
}
}

2
2018/src/samples/22.txt Normal file
View File

@@ -0,0 +1,2 @@
depth: 510
target: 10,10