mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Implement day 11.
Whelp, this was really annoying.
This commit is contained in:
4
2016/inputs/11.txt
Normal file
4
2016/inputs/11.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
The first floor contains a polonium generator, a thulium generator, a thulium-compatible microchip, a promethium generator, a ruthenium generator, a ruthenium-compatible microchip, a cobalt generator, and a cobalt-compatible microchip.
|
||||||
|
The second floor contains a polonium-compatible microchip and a promethium-compatible microchip.
|
||||||
|
The third floor contains nothing relevant.
|
||||||
|
The fourth floor contains nothing relevant.
|
||||||
191
2016/src/day11.rs
Normal file
191
2016/src/day11.rs
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
use common;
|
||||||
|
use regex;
|
||||||
|
use std::io;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::collections::{HashSet,HashMap,VecDeque};
|
||||||
|
|
||||||
|
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
struct State {
|
||||||
|
pub elevator: usize,
|
||||||
|
pub generators: [u8;4],
|
||||||
|
pub chips: [u8;4],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
pub fn is_valid(&self) -> bool {
|
||||||
|
for (&generators, &chips) in self.generators.iter().zip(self.chips.iter()) {
|
||||||
|
let matched = generators & chips;
|
||||||
|
|
||||||
|
if (chips & !matched) != 0 && generators != 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_done(&self) -> bool {
|
||||||
|
for i in 0..3usize {
|
||||||
|
if self.generators[i] != 0 || self.chips[i] != 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Day11 {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Day11 {
|
||||||
|
pub fn new() -> Day11 {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_modifications(new_states: &mut Vec<State>, cur: &State,
|
||||||
|
chip_modifications: u8, generator_modifications: u8) {
|
||||||
|
if cur.elevator > 0 {
|
||||||
|
let mut copy = cur.clone();
|
||||||
|
copy.chips[cur.elevator] &= !chip_modifications;
|
||||||
|
copy.chips[cur.elevator - 1] |= chip_modifications;
|
||||||
|
copy.generators[cur.elevator] &= !generator_modifications;
|
||||||
|
copy.generators[cur.elevator - 1] |= generator_modifications;
|
||||||
|
copy.elevator -= 1;
|
||||||
|
if copy.is_valid() {
|
||||||
|
new_states.push(copy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cur.elevator < 3 {
|
||||||
|
let mut copy= cur.clone();
|
||||||
|
copy.chips[cur.elevator] &= !chip_modifications;
|
||||||
|
copy.chips[cur.elevator + 1] |= chip_modifications;
|
||||||
|
copy.generators[cur.elevator] &= !generator_modifications;
|
||||||
|
copy.generators[cur.elevator + 1] |= generator_modifications;
|
||||||
|
copy.elevator += 1;
|
||||||
|
if copy.is_valid() {
|
||||||
|
new_states.push(copy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_state(input: &mut io::Read) -> State {
|
||||||
|
let reader = io::BufReader::new(input);
|
||||||
|
let mut state: State = Default::default();
|
||||||
|
let mut elements = HashMap::new();
|
||||||
|
|
||||||
|
let matcher = regex::Regex::new(r"a (\w+)(-compatible)? (microchip|generator)").unwrap();
|
||||||
|
|
||||||
|
for (i, line) in reader.lines().enumerate() {
|
||||||
|
let contents = line.unwrap();
|
||||||
|
for result in matcher.captures_iter(&contents) {
|
||||||
|
let element = result.get(1).unwrap().as_str();
|
||||||
|
if elements.get(element) == None {
|
||||||
|
let new_id = elements.len();
|
||||||
|
elements.insert(element.to_string(), new_id);
|
||||||
|
}
|
||||||
|
let id = *elements.get(element).unwrap();
|
||||||
|
|
||||||
|
let index = 1 << id;
|
||||||
|
match result.get(3).unwrap().as_str() {
|
||||||
|
"microchip" => {state.chips[i] |= index},
|
||||||
|
"generator" => {state.generators[i] |= index},
|
||||||
|
_ => panic!("Invalid component type."),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve(initial: State) -> String {
|
||||||
|
let mut todo = VecDeque::new();
|
||||||
|
let mut visited = HashSet::new();
|
||||||
|
|
||||||
|
todo.push_back((0, initial));
|
||||||
|
visited.insert(initial);
|
||||||
|
assert!(initial.is_valid());
|
||||||
|
|
||||||
|
while let Some((dist, state)) = todo.pop_front() {
|
||||||
|
if state.is_done() {
|
||||||
|
return format!("{}", dist);
|
||||||
|
}
|
||||||
|
let new_dist = dist + 1;
|
||||||
|
let chips: u8 = state.chips[state.elevator];
|
||||||
|
let generators: u8 = state.generators[state.elevator];
|
||||||
|
let mut new_states = Vec::new();
|
||||||
|
|
||||||
|
// Move two chips
|
||||||
|
for i in 0..8u8 {
|
||||||
|
for j in 0..=i {
|
||||||
|
if ((1 << i) & chips) == 0 || ((1 << j) & chips) == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let modification = (1 << i) | (1 << j);
|
||||||
|
Day11::add_modifications(&mut new_states, &state, modification, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Move two generators
|
||||||
|
for i in 0..8u8 {
|
||||||
|
for j in 0..=i {
|
||||||
|
if ((1 << i) & generators) == 0 || ((1 << j) & generators) == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let modification = (1 << i) | (1 << j);
|
||||||
|
Day11::add_modifications(&mut new_states, &state, 0, modification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Move one of each
|
||||||
|
for i in 0..8u8 {
|
||||||
|
for j in 0..8u8 {
|
||||||
|
if ((1 << i) & chips) == 0 || ((1 << j) & generators) == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Day11::add_modifications(&mut new_states, &state, 1 << i, 1 << j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for new_state in new_states {
|
||||||
|
if !visited.contains(&new_state) {
|
||||||
|
visited.insert(new_state);
|
||||||
|
todo.push_back((new_dist, new_state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl common::Solution for Day11 {
|
||||||
|
fn part1(&mut self, input: &mut io::Read) -> String {
|
||||||
|
let initial = Day11::read_state(input);
|
||||||
|
Day11::solve(initial)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2(&mut self, input: &mut io::Read) -> String {
|
||||||
|
let mut initial = Day11::read_state(input);
|
||||||
|
// Just add the new ones as the most significant bits
|
||||||
|
let modifier: u8 = 0b11000000;
|
||||||
|
initial.generators[0] |= modifier;
|
||||||
|
initial.chips[0] |= modifier;
|
||||||
|
Day11::solve(initial)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use common::Solution;
|
||||||
|
|
||||||
|
const SAMPLE: &[u8] = b"The first floor contains a hydrogen-compatible microchip and a lithium-compatible microchip.
|
||||||
|
The second floor contains a hydrogen generator.
|
||||||
|
The third floor contains a lithium generator.
|
||||||
|
The fourth floor contains nothing relevant.";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part1() {
|
||||||
|
let mut instance = Day11::new();
|
||||||
|
assert_eq!("11", instance.part1(&mut SAMPLE));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ use std::io;
|
|||||||
pub mod common;
|
pub mod common;
|
||||||
pub mod day1;
|
pub mod day1;
|
||||||
pub mod day2;
|
pub mod day2;
|
||||||
|
pub mod day11;
|
||||||
pub mod day12;
|
pub mod day12;
|
||||||
pub mod day15;
|
pub mod day15;
|
||||||
pub mod day16;
|
pub mod day16;
|
||||||
@@ -21,6 +22,7 @@ fn get_impl(day: &str) -> Box<common::Solution> {
|
|||||||
match day.parse() {
|
match day.parse() {
|
||||||
Ok(1) => { Box::new(day1::Day1::new()) }
|
Ok(1) => { Box::new(day1::Day1::new()) }
|
||||||
Ok(2) => { Box::new(day2::Day2::new()) }
|
Ok(2) => { Box::new(day2::Day2::new()) }
|
||||||
|
Ok(11) => Box::new(day11::Day11::new()),
|
||||||
Ok(12) => { Box::new(day12::Day12::new()) }
|
Ok(12) => { Box::new(day12::Day12::new()) }
|
||||||
Ok(15) => { Box::new(day15::Day15::new()) }
|
Ok(15) => { Box::new(day15::Day15::new()) }
|
||||||
Ok(16) => { Box::new(day16::Day16::new()) }
|
Ok(16) => { Box::new(day16::Day16::new()) }
|
||||||
|
|||||||
Reference in New Issue
Block a user