Implement day 12 part 2.

This in no way should work, but it does, at least for my input.
This commit is contained in:
2018-12-12 12:44:27 +01:00
parent fd3e509841
commit 247613555b

View File

@@ -1,9 +1,13 @@
use std::collections::HashMap;
use std::io::BufRead; use std::io::BufRead;
use std::io::BufReader; use std::io::BufReader;
use std::io::Read; use std::io::Read;
use std::iter::FromIterator;
use common::Solution; use common::Solution;
type State = Vec<(i64, bool)>;
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct Day12 { pub struct Day12 {
productions: [bool; 32], productions: [bool; 32],
@@ -17,15 +21,22 @@ fn char_bool(c: char) -> bool {
} }
} }
fn print_state(state: &[(i32, bool)]) { fn print_state(state: &State) -> String {
let mut buf = String::with_capacity(state.len());
for &(_, b) in state { for &(_, b) in state {
if b { if b {
print!("#"); buf.push('#');
} else { } else {
print!("."); buf.push('.');
} }
} }
println!(); buf
}
fn state_from_string(representation: &str, offset: i64) -> State {
Vec::from_iter(representation.chars()
.enumerate()
.map(|(i, c)| (i as i64 + offset, char_bool(c))))
} }
impl Day12 { impl Day12 {
@@ -33,7 +44,7 @@ impl Day12 {
Default::default() Default::default()
} }
fn read_input(&mut self, input: &mut Read) -> Vec<(i32, bool)> { fn read_input(&mut self, input: &mut Read) -> State {
let mut state = Vec::new(); let mut state = Vec::new();
let mut reader = BufReader::new(input); let mut reader = BufReader::new(input);
{ {
@@ -41,7 +52,7 @@ impl Day12 {
reader.read_line(&mut line).unwrap(); reader.read_line(&mut line).unwrap();
for (idx, c) in line.trim().chars().skip("initial state: ".len()).enumerate() { for (idx, c) in line.trim().chars().skip("initial state: ".len()).enumerate() {
state.push((idx as i32, char_bool(c))); state.push((idx as i64, char_bool(c)));
} }
} }
@@ -66,7 +77,7 @@ impl Day12 {
state state
} }
fn simulate(&self, state: &[(i32, bool)]) -> Vec<(i32, bool)> { fn simulate(&self, state: &State) -> State {
let mut new_state = Vec::new(); let mut new_state = Vec::new();
let mut index = 0; let mut index = 0;
let mut last_idx = None; let mut last_idx = None;
@@ -101,38 +112,56 @@ impl Day12 {
new_state new_state
} }
fn simulate_n(&self, mut state: State, n: usize) -> State {
for _ in 0..n {
state = self.simulate(&state);
}
state
}
fn sum(&self, state: &State) -> i64 {
state.iter()
.filter(|&&(_, x)| x)
.map(|&(i, _)| i)
.sum()
}
} }
impl Solution for Day12 { impl Solution for Day12 {
fn part1(&mut self, input: &mut Read) -> String { fn part1(&mut self, input: &mut Read) -> String {
let mut state = self.read_input(input); let mut state = self.read_input(input);
print_state(&state); state = self.simulate_n(state, 20);
for _ in 1..=20 {
state = self.simulate(&state);
}
let total: i32 = state.iter() format!("{}", self.sum(&state))
.filter(|&&(_, x)| x)
.map(|&(i, _)| i)
.sum();
format!("{}", total)
} }
fn part2(&mut self, input: &mut Read) -> String { fn part2(&mut self, input: &mut Read) -> String {
// Note: this is way too slow // Note: this is way too slow
let mut state = self.read_input(input); let mut state = self.read_input(input);
print_state(&state); let mut seen = HashMap::new();
for _ in 1..=50000000000i64 { let mut time = 1i64;
const TARGET_TIME: i64 = 50000000000;
loop {
state = self.simulate(&state); state = self.simulate(&state);
let &(offset, _) = state.first().unwrap();
let representation = print_state(&state);
if let Some((o_offset, o_time)) = seen.get(&representation) {
let remaining_time = TARGET_TIME - o_time;
let cycle_length = time - o_time;
let iterations_skipped = remaining_time / cycle_length;
let remainder = remaining_time % cycle_length;
let new_offset = o_offset + iterations_skipped * (offset - o_offset);
state = state_from_string(&representation, new_offset);
state = self.simulate_n(state, remainder as usize);
return format!("{}", self.sum(&state));
}
seen.insert(representation, (offset, time));
time += 1;
} }
let total: i32 = state.iter()
.filter(|&&(_, x)| x)
.map(|&(i, _)| i)
.sum();
format!("{}", total)
} }
} }