-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDay14.c
More file actions
106 lines (80 loc) · 3.12 KB
/
Day14.c
File metadata and controls
106 lines (80 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include "Helpers.c"
#define TEMPLATE_CAP 32
static int parse(const char *input, uint8_t template[TEMPLATE_CAP], uint8_t rules[26][26]) {
int charsRead = 0;
assert(sscanf(input, "%31s\n%n", template, &charsRead) != EOF);
int n = charsRead - 2;
input += charsRead;
uint8_t p0 = 0;
uint8_t p1 = 0;
uint8_t r = 0;
while (sscanf(input, "%c%c -> %c\n%n", &p0, &p1, &r, &charsRead) == 3) {
assert(p0 <= 'Z' && p1 <= 'Z' && r <= 'Z');
rules[p0 - 'A'][p1 - 'A'] = r - 'A';
input += charsRead;
}
return n;
}
static int64_t pairFromTemplate(int n, const uint8_t template[n], const uint8_t rules[26][26], int steps) {
// Allocate stack memory for all possible pair combinations for all steps.
int64_t pairsByStep[steps + 1][26][26];
memset(pairsByStep, 0, sizeof(int64_t) * 26 * 26 * (uint32_t)(steps + 1));
// Insert initial pairs from template into step 0.
for (int i = 0; i < n - 1; ++i) {
++pairsByStep[0][template[i] - 'A'][template[i + 1] - 'A'];
}
for (int step = 1; step <= steps; ++step) {
// For every pair possibility, if pair exist from previous step, insert new pairs by rules.
for (int p0 = 0; p0 < 26; ++p0) {
for (int p1 = 0; p1 < 26; ++p1) {
if (pairsByStep[step - 1][p0][p1] > 0) {
uint8_t insert = rules[p0][p1];
assert(insert);
// p0 and insert pair
pairsByStep[step][p0][insert] += pairsByStep[step - 1][p0][p1];
// insert and p1 pair
pairsByStep[step][insert][p1] += pairsByStep[step - 1][p0][p1];
}
}
}
}
int64_t twiceCounts[26] = {0};
// All but first and last character are counted twice due to insert rules.
twiceCounts[template[0] - 'A'] = 1;
twiceCounts[template[n - 1] - 'A'] = 1;
for (int i = 0; i < 26; ++i) {
for (int j = 0; j < 26; ++j) {
twiceCounts[i] += pairsByStep[steps][i][j];
twiceCounts[j] += pairsByStep[steps][i][j];
}
}
int64_t min = INT64_MAX;
int64_t max = 0;
for (int i = 0; i < 26; ++i) {
if (twiceCounts[i] > 0) {
int64_t count = twiceCounts[i] / 2;
min = count < min ? count : min;
max = count > max ? count : max;
}
}
return max - min;
}
static int64_t partOne(int n, const uint8_t template[n], const uint8_t rules[26][26]) {
return pairFromTemplate(n, template, rules, 10);
}
static int64_t partTwo(int n, const uint8_t template[n], const uint8_t rules[26][26]) {
return pairFromTemplate(n, template, rules, 40);
}
int main() {
const char *input = Helpers_readInputFile(__FILE__);
uint8_t template[TEMPLATE_CAP] = {0};
uint8_t rules[26][26] = {0};
int n = parse(input, template, rules);
Helpers_assert(PART1, Helpers_clock(),
partOne(n, template, rules),
1588, 2947);
Helpers_assert(PART2, Helpers_clock(),
partTwo(n, template, rules),
2188189693529, 3232426226464);
return 0;
}