Completed day 12 part 1
This commit is contained in:
parent
0d84ff39b8
commit
e5f615cf48
34
inputs/12.txt
Normal file
34
inputs/12.txt
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
initial state: ##.##.##..#..#.#.#.#...#...#####.###...#####.##..#####.#..#.##..#..#.#...#...##.##...#.##......####.
|
||||||
|
|
||||||
|
##.#. => #
|
||||||
|
#.#.. => #
|
||||||
|
##... => .
|
||||||
|
...## => #
|
||||||
|
###.# => #
|
||||||
|
#.##. => #
|
||||||
|
#.### => #
|
||||||
|
####. => #
|
||||||
|
.#..# => #
|
||||||
|
...#. => .
|
||||||
|
#..#. => .
|
||||||
|
#.#.# => .
|
||||||
|
.##.# => .
|
||||||
|
..#.. => .
|
||||||
|
.#.## => #
|
||||||
|
..##. => .
|
||||||
|
.#.#. => #
|
||||||
|
#..## => #
|
||||||
|
..#.# => #
|
||||||
|
#.... => .
|
||||||
|
..### => .
|
||||||
|
#...# => .
|
||||||
|
##### => #
|
||||||
|
###.. => #
|
||||||
|
....# => .
|
||||||
|
##.## => #
|
||||||
|
.#### => .
|
||||||
|
..... => .
|
||||||
|
##..# => #
|
||||||
|
.##.. => .
|
||||||
|
.###. => .
|
||||||
|
.#... => #
|
16
inputs/12_test.txt
Normal file
16
inputs/12_test.txt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
initial state: #..#.#..##......###...###
|
||||||
|
|
||||||
|
...## => #
|
||||||
|
..#.. => #
|
||||||
|
.#... => #
|
||||||
|
.#.#. => #
|
||||||
|
.#.## => #
|
||||||
|
.##.. => #
|
||||||
|
.#### => #
|
||||||
|
#.#.# => #
|
||||||
|
#.### => #
|
||||||
|
##.#. => #
|
||||||
|
##.## => #
|
||||||
|
###.. => #
|
||||||
|
###.# => #
|
||||||
|
####. => #
|
265
src/day12.rs
Normal file
265
src/day12.rs
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
extern crate regex;
|
||||||
|
|
||||||
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt;
|
||||||
|
use std::fs;
|
||||||
|
use std::result;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
type Result<T> = result::Result<T, Box<Error>>;
|
||||||
|
|
||||||
|
const INPUT: &str = "inputs/12.txt";
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
struct Pots(VecDeque<bool>);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
struct SpreadRules(HashMap<[bool; 5], bool>);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
struct GrowthSimulation {
|
||||||
|
pots: Pots,
|
||||||
|
spread_rules: SpreadRules,
|
||||||
|
generations: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Pots {
|
||||||
|
#[allow(clippy::write_with_newline)]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
for pot in self.0.iter() {
|
||||||
|
if *pot {
|
||||||
|
write!(f, "#")?;
|
||||||
|
} else {
|
||||||
|
write!(f, ".")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write!(f, "\n")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SpreadRules {
|
||||||
|
#[allow(clippy::write_with_newline)]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
for (pattern, result) in self.0.iter() {
|
||||||
|
for pot in pattern {
|
||||||
|
if *pot {
|
||||||
|
write!(f, "#")?;
|
||||||
|
} else {
|
||||||
|
write!(f, ".")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write!(f, " => ")?;
|
||||||
|
if *result {
|
||||||
|
write!(f, "#")?;
|
||||||
|
} else {
|
||||||
|
write!(f, ".")?;
|
||||||
|
}
|
||||||
|
write!(f, "\n")?;
|
||||||
|
}
|
||||||
|
write!(f, "\n")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for GrowthSimulation {
|
||||||
|
#[allow(clippy::write_with_newline)]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.pots)?;
|
||||||
|
write!(f, "\n")?;
|
||||||
|
write!(f, "{}", self.spread_rules)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for GrowthSimulation {
|
||||||
|
type Err = Box<Error>;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<GrowthSimulation> {
|
||||||
|
let sections: Vec<&str> = s.split("\n\n").collect();
|
||||||
|
let (initial_state_str, spread_rules_str) = (sections[0], sections[1]);
|
||||||
|
let mut pots = Pots(VecDeque::new());
|
||||||
|
let mut spread_rules = SpreadRules(HashMap::new());
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref initial_state_regex: Regex =
|
||||||
|
Regex::new(r"initial state: (?P<initial_state>[#.]+)").unwrap();
|
||||||
|
static ref spread_rules_regex: Regex =
|
||||||
|
Regex::new(r"(?P<pattern>[#.]{5}) => (?P<result>[#.])").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let initial_state_captures = match initial_state_regex.captures(initial_state_str) {
|
||||||
|
None => {
|
||||||
|
return Err(From::from(
|
||||||
|
"Malformed initial state, no fields could be found",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Some(captures) => captures,
|
||||||
|
};
|
||||||
|
|
||||||
|
for pot in initial_state_captures["initial_state"].chars() {
|
||||||
|
pots.0.push_back(pot == '#');
|
||||||
|
}
|
||||||
|
|
||||||
|
for rule in spread_rules_str.lines() {
|
||||||
|
let spread_rules_captures = match spread_rules_regex.captures(rule) {
|
||||||
|
None => {
|
||||||
|
return Err(From::from(
|
||||||
|
"Malformed spread rules, no fields could be found",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Some(captures) => captures,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut pattern = [false; 5];
|
||||||
|
let pattern_vec: Vec<bool> = spread_rules_captures["pattern"]
|
||||||
|
.chars()
|
||||||
|
.map(|c| c == '#')
|
||||||
|
.collect();
|
||||||
|
pattern.copy_from_slice(&pattern_vec);
|
||||||
|
let result = &spread_rules_captures["result"] == "#";
|
||||||
|
spread_rules.0.insert(pattern, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(GrowthSimulation { pots, spread_rules, generations: 0 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GrowthSimulation {
|
||||||
|
fn advance_generation(&mut self) {
|
||||||
|
let mut next_generation = VecDeque::new();
|
||||||
|
let padding = &[false; 4];
|
||||||
|
let pots_slice = self.pots.0.as_slices();
|
||||||
|
let pots_slice = [padding, pots_slice.0, pots_slice.1, padding].concat();
|
||||||
|
for (index, pot_window) in pots_slice.windows(5).enumerate() {
|
||||||
|
match self.spread_rules.0.get(pot_window) {
|
||||||
|
Some(result) => {
|
||||||
|
next_generation.push_back(*result);
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
next_generation.push_back(pots_slice[2]);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.pots = Pots(next_generation);
|
||||||
|
self.generations += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sum_plant_indices(&self) -> i32 {
|
||||||
|
let mut sum: i32 = 0;
|
||||||
|
for (index, pot) in self.pots.0.iter().enumerate() {
|
||||||
|
if *pot {
|
||||||
|
let shifted_index = index as i32 - self.generations as i32 * 2;
|
||||||
|
sum += shifted_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_initial_state_and_rules(filename: &str) -> Result<GrowthSimulation> {
|
||||||
|
let input = fs::read_to_string(filename)?;
|
||||||
|
Ok(input.parse()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn solve_part1() -> Result<i32> {
|
||||||
|
let mut growth_sim = read_initial_state_and_rules(INPUT)?;
|
||||||
|
for _ in 0..20 {
|
||||||
|
growth_sim.advance_generation();
|
||||||
|
}
|
||||||
|
Ok(growth_sim.sum_plant_indices())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn solve_part2() -> Result<i32> {
|
||||||
|
let mut growth_sim = read_initial_state_and_rules(INPUT)?;
|
||||||
|
for _ in 0..50_000_000_000_i64 {
|
||||||
|
growth_sim.advance_generation();
|
||||||
|
}
|
||||||
|
Ok(growth_sim.sum_plant_indices())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const TEST_INPUT: &str = "inputs/12_test.txt";
|
||||||
|
fn test_growth_sim() -> GrowthSimulation {
|
||||||
|
GrowthSimulation {
|
||||||
|
pots: Pots(VecDeque::from(vec![
|
||||||
|
true, false, false, true, false, true, false, false, true, true, false, false,
|
||||||
|
false, false, false, false, true, true, true, false, false, false, true, true,
|
||||||
|
true,
|
||||||
|
])),
|
||||||
|
spread_rules: SpreadRules([
|
||||||
|
([true, true, true, true, false], true),
|
||||||
|
([true, true, false, true, true], true),
|
||||||
|
([false, false, true, false, false], true),
|
||||||
|
([false, true, false, false, false], true),
|
||||||
|
([true, true, false, true, false], true),
|
||||||
|
([false, true, true, true, true], true),
|
||||||
|
([true, false, true, true, true], true),
|
||||||
|
([true, true, true, false, true], true),
|
||||||
|
([false, true, false, true, true], true),
|
||||||
|
([true, false, true, false, true], true),
|
||||||
|
([false, true, false, true, false], true),
|
||||||
|
([false, true, true, false, false], true),
|
||||||
|
([true, true, true, false, false], true),
|
||||||
|
([false, false, false, true, true], true),
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect()),
|
||||||
|
generations: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reads_initial_state_and_rules_file() {
|
||||||
|
let growth_sim = read_initial_state_and_rules(TEST_INPUT).unwrap();
|
||||||
|
assert_eq!(growth_sim, test_growth_sim());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn displays_growth_simulation() {
|
||||||
|
assert_eq!(
|
||||||
|
format!("{}", test_growth_sim()).lines().collect::<Vec<&str>>().sort(),
|
||||||
|
vec![
|
||||||
|
"#..#.#..##......###...###",
|
||||||
|
"",
|
||||||
|
"####. => #",
|
||||||
|
"##.## => #",
|
||||||
|
"..#.. => #",
|
||||||
|
".#... => #",
|
||||||
|
"##.#. => #",
|
||||||
|
".#### => #",
|
||||||
|
"#.### => #",
|
||||||
|
"###.# => #",
|
||||||
|
".#.## => #",
|
||||||
|
"#.#.# => #",
|
||||||
|
".#.#. => #",
|
||||||
|
".##.. => #",
|
||||||
|
"###.. => #",
|
||||||
|
"...## => #",
|
||||||
|
].sort()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn advances_simulation_by_one_generation() {
|
||||||
|
let mut growth_sim = test_growth_sim();
|
||||||
|
growth_sim.advance_generation();
|
||||||
|
assert_eq!(format!("{}", growth_sim.pots), "..#...#....#.....#..#..#..#..\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn returns_correct_sum_after_20_generations() {
|
||||||
|
let mut growth_sim = test_growth_sim();
|
||||||
|
for _ in 0..20 {
|
||||||
|
growth_sim.advance_generation();
|
||||||
|
}
|
||||||
|
assert_eq!(growth_sim.sum_plant_indices(), 325);
|
||||||
|
}
|
||||||
|
}
|
15
src/main.rs
15
src/main.rs
@ -14,6 +14,7 @@ mod day8;
|
|||||||
mod day9;
|
mod day9;
|
||||||
mod day10;
|
mod day10;
|
||||||
mod day11;
|
mod day11;
|
||||||
|
mod day12;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// println!("Day 1:");
|
// println!("Day 1:");
|
||||||
@ -47,10 +48,12 @@ fn main() {
|
|||||||
// let parts = day10::solve_parts().unwrap();
|
// let parts = day10::solve_parts().unwrap();
|
||||||
// println!("{}", parts.0);
|
// println!("{}", parts.0);
|
||||||
// println!("{}", parts.1);
|
// println!("{}", parts.1);
|
||||||
println!("Day 11:");
|
// println!("Day 11:");
|
||||||
let part1 = day11::solve_part1().unwrap();
|
// let part1 = day11::solve_part1().unwrap();
|
||||||
println!("{},{}", part1.coord.x, part1.coord.y);
|
// println!("{},{}", part1.coord.x, part1.coord.y);
|
||||||
let part2 = day11::solve_part2().unwrap();
|
// let part2 = day11::solve_part2().unwrap();
|
||||||
println!("{},{},{}", part2.coord.x, part2.coord.y, part2.size);
|
// println!("{},{},{}", part2.coord.x, part2.coord.y, part2.size);
|
||||||
// println!("{}", parts.1);
|
println!("Day 12:");
|
||||||
|
println!("{}", day12::solve_part1().unwrap());
|
||||||
|
println!("{}", day12::solve_part2().unwrap());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user