mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Implement day 22.
This commit is contained in:
@@ -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
2
2018/src/samples/22.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
depth: 510
|
||||||
|
target: 10,10
|
||||||
Reference in New Issue
Block a user