-
Notifications
You must be signed in to change notification settings - Fork 2
/
07.c
184 lines (154 loc) · 4.16 KB
/
07.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include "adventofcode.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define PUZZLE_NAME "Day 7: The Sum Of Its Parts"
struct step {
char name;
char done;
char busy;
size_t nprereqs;
struct step *prereqs[16];
};
// step_byname finds the step with the given name
static struct step *step_byname(struct step *steps, size_t nsteps, char name) {
for (size_t i = 0; i < nsteps; i++) {
if (steps[i].name == name) {
return &steps[i];
}
}
return NULL;
}
// step_next finds the first available step that's not already done in an
// alphabetically sorted list of steps
static struct step *step_next(struct step **steps, size_t nsteps) {
for (size_t i = 0; i < nsteps; i++) {
struct step *a = steps[i];
if (a->done || a->busy)
continue;
int ready = 1;
for (size_t r = 0; r < a->nprereqs; r++) {
if (a->prereqs[r]->done == 0) {
ready = 0;
break;
}
}
if (ready == 1) {
return a;
}
}
return NULL;
}
static int step_compare(const void *p1, const void *p2) {
const struct step *a = *(struct step **)p1;
const struct step *b = *(struct step **)p2;
return (a->name > b->name) - (a->name < b->name);
}
static void pt1(char *buf, struct step **steps, const size_t nsteps) {
char *o = buf;
while (1) {
struct step *cur = step_next(steps, nsteps);
if (cur == NULL)
break;
*o++ = cur->name;
cur->done = 1;
}
*o = 0x0;
// clean-up: mark all tasks as unfinished again
for (size_t i = 0; i < nsteps; i++)
steps[i]->done = 0;
}
static int pt2(struct step **steps, const size_t nsteps) {
#define NWORKERS 5
int delay_s = 60;
int worker_finish_times[NWORKERS];
struct step *worker_tasks[NWORKERS];
memset(worker_finish_times, 0, sizeof(*worker_finish_times) * NWORKERS);
memset(worker_tasks, 0, sizeof(struct step *) * NWORKERS);
size_t ndone = 0;
// loop over seconds
for (int s = 0;; s++) {
// first loop, mark steps as done
for (size_t w = 0; w < NWORKERS; w++) {
if (worker_finish_times[w] != s) {
continue;
}
struct step *step = worker_tasks[w];
if (step != NULL) {
step->done = 1;
// exit condition: finish when we marked all tasks as done
if (++ndone == nsteps) {
return s;
}
}
worker_tasks[w] = NULL;
worker_finish_times[w] = s + 1;
}
// second loop: assign new tasks
for (size_t w = 0; w < NWORKERS; w++) {
if (worker_tasks[w] != NULL) {
continue;
}
// assign new task
struct step *step = step_next(steps, nsteps);
if (step != NULL) {
step->busy = 1;
worker_tasks[w] = step;
worker_finish_times[w] = s + delay_s + (step->name - 'A' + 1);
}
}
}
return -1;
}
int main(void) {
clock_t t = clock_time();
char input[1024 * 64] = "";
read_input_file(input, 1024 * 64, "07.txt");
struct step steps[64];
size_t nsteps = 0;
const char *s = input;
char name;
char name_prereq;
while (*s != 0x0) {
s = skip("Step ", s);
name_prereq = *s++;
s = skip(" must be finished before step ", s);
name = *s++;
while (*s != '\n' && *s != 0x0)
s++;
if (*s == '\n')
s++;
struct step *step = step_byname(steps, nsteps, name);
if (step == NULL) {
step = &steps[nsteps++];
step->name = name;
step->nprereqs = 0;
step->done = 0;
step->busy = 0;
}
struct step *prereq = step_byname(steps, nsteps, name_prereq);
if (prereq == NULL) {
prereq = &steps[nsteps++];
prereq->name = name_prereq;
prereq->nprereqs = 0;
prereq->done = 0;
prereq->busy = 0;
}
step->prereqs[step->nprereqs++] = prereq;
}
struct step *steps_sorted[64];
for (size_t i = 0; i < nsteps; i++) {
steps_sorted[i] = &steps[i];
}
qsort(steps_sorted, nsteps, sizeof(struct step *), step_compare);
// solve for pt 1
char a1[64];
pt1(a1, steps_sorted, nsteps);
int a2 = pt2(steps_sorted, nsteps);
printf("--- %s ---\n", PUZZLE_NAME);
printf("Part 1: %s\n", a1);
printf("Part 2: %d\n", a2);
printf("Time: %.2fms\n", clock_time_since(t));
return EXIT_SUCCESS;
}