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