-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay12.c
106 lines (79 loc) · 2.55 KB
/
Day12.c
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 N ((('z' << 8) | 'z') + 1)
#define CONN_CAP 8
#define START_CAVE_ID 0
#define END_CAVE_ID 1
#define BIG_CAVE_ID_MAX (('Z' << 8) | 'Z')
typedef uint16_t CaveId;
typedef struct {
int nConnections;
CaveId connections[CONN_CAP];
} Cave;
static CaveId idFromString(const char *s) {
switch (strnlen(s, 6)) {
case 5: return START_CAVE_ID;
case 3: return END_CAVE_ID;
case 2: return (CaveId)((s[0] << 8) | s[1]);
case 1: return (CaveId)((s[0] << 8) | s[0]);
default: assert(false);
}
}
static void parse(const char *input, Cave caves[N]) {
char a[8] = {0};
char b[8] = {0};
int charsRead = 0;
int filled;
while ((filled = sscanf(input, "%7[^-]-%7s\n%n", a, b, &charsRead)) == 2) {
CaveId idA = idFromString(a);
CaveId idB = idFromString(b);
caves[idA].connections[caves[idA].nConnections++] = idB;
caves[idB].connections[caves[idB].nConnections++] = idA;
assert(caves[idA].nConnections < CONN_CAP);
assert(caves[idB].nConnections < CONN_CAP);
input += charsRead;
}
}
static int countPathsHelp(const Cave caves[N], const CaveId id, const uint8_t maxVisitsOnce, uint8_t visited[N], bool hasVisitedMaxOnce) {
if (id == END_CAVE_ID) {
return 1;
}
if ((!hasVisitedMaxOnce && visited[id] >= maxVisitsOnce) ||
((hasVisitedMaxOnce || id == START_CAVE_ID) && visited[id] > 0)) {
return 0;
}
bool isSmallCave = id == START_CAVE_ID || id > BIG_CAVE_ID_MAX;
if (isSmallCave) {
++visited[id];
};
hasVisitedMaxOnce |= visited[id] >= maxVisitsOnce;
int n = 0;
for (int i = 0; i < caves[id].nConnections; ++i) {
n += countPathsHelp(caves, caves[id].connections[i], maxVisitsOnce, visited, hasVisitedMaxOnce);
}
if (visited[id] > 0) {
--visited[id];
}
return n;
}
static int countPaths(const Cave caves[N], const uint8_t maxVisitsOnce) {
uint8_t visited[N] = {0};
return countPathsHelp(caves, START_CAVE_ID, maxVisitsOnce, visited, false);
}
static int partOne(const Cave caves[N]) {
return countPaths(caves, 1);
}
static int partTwo(const Cave caves[N]) {
return countPaths(caves, 2);
}
int main() {
const char *input = Helpers_readInputFile(__FILE__);
Cave caves[N] = {0};
parse(input, caves);
Helpers_assert(PART1, Helpers_clock(),
partOne(caves),
10, 4885);
Helpers_assert(PART2, Helpers_clock(),
partTwo(caves),
36, 117095);
return 0;
}