From cfd9b4f2ad1a09bedf7f764f84448a61faab54a3 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Tue, 19 Apr 2022 20:26:02 +0200 Subject: Refile for merging repos --- 2018/src/bin/day_12.rs | 102 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 2018/src/bin/day_12.rs (limited to '2018/src/bin/day_12.rs') diff --git a/2018/src/bin/day_12.rs b/2018/src/bin/day_12.rs new file mode 100644 index 0000000..65a966d --- /dev/null +++ b/2018/src/bin/day_12.rs @@ -0,0 +1,102 @@ +extern crate advent_of_code_2018; +use advent_of_code_2018::*; + +use std::error::Error; +use std::path::PathBuf; + +use std::str::FromStr; + +// cargo watch -cs "cargo run --release --bin day_12" + +use std::collections::HashSet; + +#[derive(Debug)] +struct Rule { + input: [bool; 5], + output: bool +} + +impl FromStr for Rule { + type Err = Box; + + fn from_str(s: &str) -> Result { + //##..# => # + let mut input = [false; 5]; + let mut iter = s.chars().filter(|c| *c == '#' || *c == '.'); + for (i, c) in iter.by_ref().take(5).enumerate() { + if c == '#' { + input[i] = true; + } + } + Ok(Rule { + input, + output: iter.next() == Some('#') + }) + } +} + +impl Rule { + fn matches(&self, state: &HashSet, index: i64) -> bool { + self.input.iter().enumerate().all(|(i, expected)| { + let pot_index = index - 2 + i as i64; + *expected == state.contains(&pot_index) + }) + } +} + +fn main() -> Result<(), Box> { + let input = read_file(&PathBuf::from("inputs/12.txt"))?; + + println!("Input: {:?}", input); + + let mut initial_state: HashSet = HashSet::new(); + for (i, c) in input[0].chars().filter(|c| *c == '#' || *c == '.').enumerate() { + if c == '#' { + initial_state.insert(i as i64); + } + } + let rules = input.iter().skip(1).map(|line| line.parse()).collect::, Box>>()?; + + debug!(initial_state); + debug!(rules); + + let part1_time = 20; + let part2_time = 50000000000; + + let part1_final_state = iterate_states(&initial_state, &rules, part1_time); + let sum_of_part1_pot_numbers: i64 = part1_final_state.iter().sum(); + debug!(sum_of_part1_pot_numbers); + + let part2_final_state = iterate_states(&initial_state, &rules, part2_time); + let sum_of_part2_pot_numbers: i64 = part2_final_state.iter().sum(); + debug!(sum_of_part2_pot_numbers); + + Ok(()) +} + +fn iterate_states(initial_state: &HashSet, rules: &[Rule], time: i64) -> HashSet { + let mut current_state = initial_state.clone(); + for current_time in 0..time { + let mut new_state = HashSet::new(); + let min = current_state.iter().min().cloned().unwrap_or(-1) - 2; + let max = current_state.iter().max().cloned().unwrap_or(-1) + 2; + + for i in min..max+1 { + if rules.iter().find(|r| r.matches(¤t_state, i)).expect("No matching rule").output { + new_state.insert(i as i64); + } + } + + if current_state.iter().map(|v| v + 1).collect::>() == new_state { + // Iterations are just shifting 1 to the right at this + // point. Found by inspecting a debugging log of the + // generations. + + let remaining_iterations = time-current_time; + return current_state.iter().map(|v| v + remaining_iterations).collect::>(); + } + + current_state = new_state; + } + current_state +} -- cgit v1.2.3