Add day 14

This commit is contained in:
kageru 2021-12-14 12:10:45 +01:00
parent 74925b973d
commit b38c53b886
3 changed files with 193 additions and 0 deletions

View File

@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
fnv = "1.0.7"
impl_ops = "0.1.1"
itertools = "0.10"
paste = "1.0"

102
2021/inputs/day14 Normal file
View File

@ -0,0 +1,102 @@
PBVHVOCOCFFNBCNCCBHK
FV -> C
SS -> B
SC -> B
BP -> K
VP -> S
HK -> K
FS -> F
CC -> V
VB -> P
OP -> B
FO -> N
FH -> O
VK -> N
PV -> S
HV -> O
PF -> F
HH -> F
NK -> S
NC -> S
FC -> H
FK -> K
OO -> N
HP -> C
NN -> H
BB -> H
CN -> P
PS -> N
VF -> S
CB -> B
OH -> S
CF -> C
OK -> P
CV -> V
CS -> H
KN -> B
OV -> S
HB -> C
OS -> V
PC -> B
CK -> S
PP -> K
SN -> O
VV -> C
NS -> F
PN -> K
HS -> P
VO -> B
VC -> B
NV -> P
VS -> N
FP -> F
HO -> S
KS -> O
BN -> F
VN -> P
OC -> K
SF -> P
PO -> P
SB -> O
FN -> F
OF -> F
CP -> C
HC -> O
PH -> O
BC -> O
NO -> C
BH -> C
VH -> S
KK -> O
SV -> K
KB -> K
BS -> S
HF -> B
NH -> S
PB -> N
HN -> K
SK -> B
FB -> F
KV -> S
BF -> S
ON -> S
BV -> P
KC -> S
NB -> S
NP -> B
BK -> K
NF -> C
BO -> K
KF -> B
KH -> N
SP -> O
CO -> S
KO -> V
SO -> B
CH -> C
KP -> C
FF -> K
PK -> F
OB -> H
SH -> C

90
2021/src/bin/day14.rs Normal file
View File

@ -0,0 +1,90 @@
#![feature(array_windows)]
#![feature(test)]
extern crate test;
use aoc2021::common::*;
use fnv::FnvHashMap;
const DAY: usize = 14;
type Parsed = (FnvHashMap<[u8; 2], u8>, String);
fn parse_input(raw: &str) -> Parsed {
let (state, rules) = raw.split_once("\n\n").unwrap();
let rules = rules.lines().map(|line| line.as_bytes()).map(|bytes| ([bytes[0], bytes[1]], bytes[bytes.len() - 1])).collect();
(rules, state.to_owned())
}
fn grow_polys((rules, raw_state): &Parsed, generations: usize) -> usize {
let mut state = FnvHashMap::default();
for polymer in raw_state.as_bytes().array_windows() {
*state.entry(*polymer).or_insert(0) += 1;
}
for _ in 0..generations {
for ([p1, p2], quantity) in state.clone() {
let output = rules[&[p1, p2]];
*state.entry([p1, output]).or_insert(0) += quantity;
*state.entry([output, p2]).or_insert(0) += quantity;
*state.get_mut(&[p1, p2]).unwrap() -= quantity;
}
}
let mut charcounts = FnvHashMap::default();
for (p, q) in state.into_iter().flat_map(|([p1, p2], q)| [(p1, q), (p2, q)]) {
*charcounts.entry(p).or_insert(0) += q;
}
for (&p, q) in charcounts.iter_mut() {
// This implementation counts each element except the very first and very last twice.
// We add 1 for those and then divide by 2.
*q += (p == raw_state.bytes().next().unwrap()) as usize;
*q += (p == raw_state.bytes().last().unwrap()) as usize;
*q /= 2;
}
charcounts.values().max().unwrap() - charcounts.values().filter(|&&q| q != 0).min().unwrap()
}
fn part1(parsed: &Parsed) -> usize {
grow_polys(parsed, 10)
}
fn part2(parsed: &Parsed) -> usize {
grow_polys(parsed, 40)
}
fn main() {
let input = parse_input(&read_file(DAY));
println!("Part 1: {}", part1(&input));
println!("Part 2: {}", part2(&input));
}
#[cfg(test)]
mod tests {
use super::*;
use aoc2021::*;
const TEST_INPUT: &str = "NNCB
CH -> B
HH -> N
CB -> H
NH -> C
HB -> C
HC -> B
HN -> C
NN -> C
BH -> H
NC -> B
NB -> B
BN -> B
BB -> N
BC -> B
CC -> N
CN -> C";
test!(part1() == 1588);
test!(part2() == 2188189693529);
bench!(part1() == 3587);
bench!(part2() == 3906445077999);
bench_input!(input_size => 120);
fn input_size((m, s): &Parsed) -> usize {
m.len() + s.len()
}
}