parent
caa0ec1553
commit
a09a82c05d
@ -0,0 +1,161 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
use advent_of_code::main;
|
||||||
|
|
||||||
|
main!();
|
||||||
|
|
||||||
|
fn solve(input: &str) -> Result<String, Box<Error>> {
|
||||||
|
let mut generation: Generation = input.parse()?;
|
||||||
|
for _ in 0..19 {
|
||||||
|
generation.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
let pots = generation.next().unwrap();
|
||||||
|
let indices: Vec<_> = pots.iter().filter(|(_,&v)| v).map(|(&k,_)| k).collect();
|
||||||
|
let output: isize = indices.iter().sum();
|
||||||
|
|
||||||
|
Ok(output.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_solve() {
|
||||||
|
let input = r"
|
||||||
|
initial state: #..#.#..##......###...###
|
||||||
|
|
||||||
|
...## => #
|
||||||
|
..#.. => #
|
||||||
|
.#... => #
|
||||||
|
.#.#. => #
|
||||||
|
.#.## => #
|
||||||
|
.##.. => #
|
||||||
|
.#### => #
|
||||||
|
#.#.# => #
|
||||||
|
#.### => #
|
||||||
|
##.#. => #
|
||||||
|
##.## => #
|
||||||
|
###.. => #
|
||||||
|
###.# => #
|
||||||
|
####. => #
|
||||||
|
";
|
||||||
|
|
||||||
|
assert_eq!(solve(&input).unwrap(), 325.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Generation {
|
||||||
|
pots: HashMap<isize, bool>,
|
||||||
|
notes: HashMap<String, bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Generation {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let plants: Vec<_> = self
|
||||||
|
.pots
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, &v)| v)
|
||||||
|
.map(|(&k, _)| k)
|
||||||
|
.collect();
|
||||||
|
let min = *plants.iter().min().unwrap();
|
||||||
|
let max = *plants.iter().max().unwrap();
|
||||||
|
let s: String = (min..=max)
|
||||||
|
.map(|x| self.pots.get(&x).unwrap_or_else(|| &false))
|
||||||
|
.map(|&x| if x { '#' } else { '.' })
|
||||||
|
.collect();
|
||||||
|
write!(f, "{}", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for Generation {
|
||||||
|
type Item = HashMap<isize, bool>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let plants: Vec<_> = self
|
||||||
|
.pots
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, &v)| v)
|
||||||
|
.map(|(&k, _)| k)
|
||||||
|
.collect();
|
||||||
|
let min = *plants.iter().min().unwrap() - 2;
|
||||||
|
let max = *plants.iter().max().unwrap() + 2;
|
||||||
|
self.pots = (min..=max)
|
||||||
|
.map(|i| {
|
||||||
|
let key: String = ((i - 2)..=(i + 2))
|
||||||
|
.map(|x| self.pots.get(&x).unwrap_or_else(|| &false))
|
||||||
|
.map(|&x| if x { '#' } else { '.' })
|
||||||
|
.collect();
|
||||||
|
let value = *self.notes.get(&key).unwrap_or_else(|| &false);
|
||||||
|
(i, value)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Some(self.pots.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_generation() {
|
||||||
|
let input = r"
|
||||||
|
initial state: #..#.#..##......###...###
|
||||||
|
|
||||||
|
...## => #
|
||||||
|
..#.. => #
|
||||||
|
.#... => #
|
||||||
|
.#.#. => #
|
||||||
|
.#.## => #
|
||||||
|
.##.. => #
|
||||||
|
.#### => #
|
||||||
|
#.#.# => #
|
||||||
|
#.### => #
|
||||||
|
##.#. => #
|
||||||
|
##.## => #
|
||||||
|
###.. => #
|
||||||
|
###.# => #
|
||||||
|
####. => #
|
||||||
|
";
|
||||||
|
let mut generation: Generation = input.parse().unwrap();
|
||||||
|
let pots = generation.pots.clone();
|
||||||
|
assert!(pots.get(&0).unwrap());
|
||||||
|
assert!(pots.get(&3).unwrap());
|
||||||
|
assert!(!pots.get(&4).unwrap());
|
||||||
|
|
||||||
|
let pots = generation.next().unwrap();
|
||||||
|
assert!(pots.get(&0).unwrap());
|
||||||
|
assert!(!pots.get(&3).unwrap());
|
||||||
|
assert!(pots.get(&4).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Generation {
|
||||||
|
type Err = Box<Error>;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let mut lines = s.trim().lines();
|
||||||
|
|
||||||
|
let initial_state = lines.next().unwrap();
|
||||||
|
let pots = Regex::new(r"[.#]+")
|
||||||
|
.ok()
|
||||||
|
.and_then(|re| re.find(initial_state))
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.chars()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, c)| (i as isize, c == '#'))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
lines.next(); // skip blank line
|
||||||
|
|
||||||
|
let notes = lines
|
||||||
|
.map(|line| {
|
||||||
|
let mut note = line.split(" => ");
|
||||||
|
let key = note.next().unwrap();
|
||||||
|
let value = note.next().unwrap() == "#";
|
||||||
|
(key.into(), value)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(Generation { pots, notes })
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue