1use crate::util::iter::*;
11
12type Elements = [u64; 26];
13type Pairs = [u64; 26 * 26];
14type Rules = Vec<Rule>;
15
16pub struct Rule {
17 from: usize,
18 to_left: usize,
19 to_right: usize,
20 element: usize,
21}
22
23impl Rule {
24 fn parse([a, b, c]: [u8; 3]) -> Rule {
25 Rule { from: pair(a, b), to_left: pair(a, c), to_right: pair(c, b), element: element(c) }
26 }
27}
28
29pub struct Input {
30 elements: Elements,
31 pairs: Pairs,
32 rules: Rules,
33}
34
35pub fn parse(input: &str) -> Input {
37 let (prefix, suffix) = input.split_once("\n\n").unwrap();
38 let prefix = prefix.trim().as_bytes();
39
40 let mut elements = [0; 26];
41 prefix.iter().for_each(|&b| elements[element(b)] += 1);
42
43 let mut pairs = [0; 26 * 26];
44 prefix.array_windows().for_each(|&[a, b]| pairs[pair(a, b)] += 1);
45
46 let rules: Vec<_> =
47 suffix.bytes().filter(u8::is_ascii_uppercase).chunk::<3>().map(Rule::parse).collect();
48
49 Input { elements, pairs, rules }
50}
51
52pub fn part1(input: &Input) -> u64 {
54 steps(input, 10)
55}
56
57pub fn part2(input: &Input) -> u64 {
59 steps(input, 40)
60}
61
62fn steps(input: &Input, rounds: usize) -> u64 {
67 let mut elements = input.elements;
68 let mut pairs = input.pairs;
69 let rules = &input.rules;
70
71 for _ in 0..rounds {
72 let mut next: Pairs = [0; 26 * 26];
73
74 for rule in rules {
75 let n = pairs[rule.from];
76 next[rule.to_left] += n;
77 next[rule.to_right] += n;
78 elements[rule.element] += n;
79 }
80
81 pairs = next;
82 }
83
84 let max = elements.iter().max().unwrap();
85 let min = elements.iter().filter(|&&n| n > 0).min().unwrap();
86 max - min
87}
88
89fn element(byte: u8) -> usize {
91 (byte - b'A') as usize
92}
93
94fn pair(first: u8, second: u8) -> usize {
96 26 * element(first) + element(second)
97}