211 lines
5.6 KiB
C
211 lines
5.6 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
|
|
typedef enum {
|
|
BEGIN_SHIFT,
|
|
FALL_ASLEEP,
|
|
WAKE_UP,
|
|
} EventType;
|
|
|
|
typedef struct {
|
|
int year;
|
|
int month;
|
|
int day;
|
|
int hour;
|
|
int minute;
|
|
int guard_number;
|
|
EventType type;
|
|
} Event;
|
|
|
|
typedef struct {
|
|
int number;
|
|
int minutes_asleep;
|
|
int asleep_at;
|
|
int sleep_schedule[60];
|
|
} Guard;
|
|
|
|
bool read_event(FILE *input, Event *event) {
|
|
int result = fscanf(input, "[%d-%d-%d %d:%d] ", &(event->year), &(event->month), &(event->day), &(event->hour), &(event->minute));
|
|
if (result != 5) return false;
|
|
|
|
char buf[80] = {0};
|
|
fgets(buf, 79, input);
|
|
|
|
if(strcmp(buf, "falls asleep\n") == 0) {
|
|
event->type = FALL_ASLEEP;
|
|
return true;
|
|
}
|
|
|
|
if(strcmp(buf, "wakes up\n") == 0) {
|
|
event->type = WAKE_UP;
|
|
return true;
|
|
}
|
|
|
|
strtok(buf, "#");
|
|
event->guard_number = atoi(strtok(NULL, " "));
|
|
event->type = BEGIN_SHIFT;
|
|
return true;
|
|
}
|
|
|
|
void print_event(Event *event) {
|
|
printf("[%4d-%02d-%02d %02d:%02d] ", event->year, event->month, event->day, event->hour, event->minute);
|
|
switch(event->type) {
|
|
case BEGIN_SHIFT:
|
|
printf("Guard #%04d begins shift\n", event->guard_number);
|
|
break;
|
|
case WAKE_UP:
|
|
printf("Guard #%04d wakes up\n", event->guard_number);
|
|
break;
|
|
case FALL_ASLEEP:
|
|
printf("Guard #%04d falls asleep\n", event->guard_number);
|
|
break;
|
|
}
|
|
}
|
|
|
|
int compare_events(const void *p1, const void *p2) {
|
|
Event *ev1 = (Event*) p1;
|
|
Event *ev2 = (Event*) p2;
|
|
if(ev1->year != ev2->year) return ev1->year - ev2->year;
|
|
if(ev1->month != ev2->month) return ev1->month - ev2->month;
|
|
if(ev1->day != ev2->day) return ev1->day - ev2->day;
|
|
if(ev1->hour != ev2->hour) return ev1->hour - ev2->hour;
|
|
if(ev1->minute != ev2->minute) return ev1->minute - ev2->minute;
|
|
return 0;
|
|
}
|
|
|
|
int part_1(FILE *input) {
|
|
rewind(input);
|
|
Guard guards[10000] = {0};
|
|
int guard_numbers[100];
|
|
int guard_count = 0;
|
|
|
|
Event events[986] = {0};
|
|
Event *event = events;
|
|
while(read_event(input, event)){
|
|
for(int i = -1; i < guard_count; i++) {
|
|
if (guard_numbers[i] == event->guard_number) goto FOUND;
|
|
}
|
|
guard_numbers[guard_count++] = event->guard_number;
|
|
FOUND:
|
|
event++;
|
|
};
|
|
|
|
qsort(events, 986, sizeof(Event), compare_events);
|
|
|
|
int current_guard;
|
|
for(int i = 0; i < 986; i++) {
|
|
Event event = events[i];
|
|
switch(event.type) {
|
|
case BEGIN_SHIFT:
|
|
current_guard = event.guard_number;
|
|
guards[current_guard].number = current_guard;
|
|
break;
|
|
case FALL_ASLEEP:
|
|
(&event)->guard_number = current_guard;
|
|
guards[current_guard].asleep_at = event.minute;
|
|
break;
|
|
case WAKE_UP:
|
|
(&event)->guard_number = current_guard;
|
|
guards[current_guard].minutes_asleep += event.minute - guards[current_guard].asleep_at;
|
|
for(int i = guards[current_guard].asleep_at; i < event.minute; i++) {
|
|
guards[current_guard].sleep_schedule[i]++;
|
|
}
|
|
break;
|
|
}
|
|
// print_event(&event);
|
|
}
|
|
|
|
Guard *sleepiest_guard = &guards[guard_numbers[0]];
|
|
for(int i = 0; i < guard_count; i++) {
|
|
Guard g = guards[guard_numbers[i]];
|
|
// printf("Guard %d was asleep for %d minutes\n", g.number, g.minutes_asleep);
|
|
if (g.minutes_asleep > sleepiest_guard->minutes_asleep) sleepiest_guard = &guards[guard_numbers[i]];
|
|
}
|
|
// printf("Guard %d was asleep for %d minutes\n", sleepiest_guard->number, sleepiest_guard->minutes_asleep);
|
|
|
|
int sleepiest_minute = 0;
|
|
for(int i = 0; i < 60; i++) {
|
|
if(sleepiest_guard->sleep_schedule[i] > sleepiest_guard->sleep_schedule[sleepiest_minute])
|
|
sleepiest_minute = i;
|
|
// printf("Minute %2d: %2d\n", i, sleepiest_guard->sleep_schedule[i]);
|
|
}
|
|
|
|
// printf("Sleepiest minute was %d with %d", sleepiest_minute, sleepiest_guard->sleep_schedule[sleepiest_minute]);
|
|
|
|
return sleepiest_minute * sleepiest_guard->number;
|
|
}
|
|
|
|
int part_2(FILE *input) {
|
|
rewind(input);
|
|
Guard guards[10000] = {0};
|
|
int guard_numbers[100];
|
|
int guard_count = 0;
|
|
|
|
Event events[986] = {0};
|
|
Event *event = events;
|
|
while(read_event(input, event)){
|
|
for(int i = -1; i < guard_count; i++) {
|
|
if (guard_numbers[i] == event->guard_number) goto FOUND;
|
|
}
|
|
guard_numbers[guard_count++] = event->guard_number;
|
|
FOUND:
|
|
event++;
|
|
};
|
|
event--;
|
|
|
|
qsort(events, 986, sizeof(Event), compare_events);
|
|
|
|
int current_guard;
|
|
for(int i = 0; i < 986; i++) {
|
|
Event event = events[i];
|
|
switch(event.type) {
|
|
case BEGIN_SHIFT:
|
|
current_guard = event.guard_number;
|
|
guards[current_guard].number = current_guard;
|
|
break;
|
|
case FALL_ASLEEP:
|
|
(&event)->guard_number = current_guard;
|
|
guards[current_guard].asleep_at = event.minute;
|
|
break;
|
|
case WAKE_UP:
|
|
(&event)->guard_number = current_guard;
|
|
guards[current_guard].minutes_asleep += event.minute - guards[current_guard].asleep_at;
|
|
for(int i = guards[current_guard].asleep_at; i < event.minute; i++) {
|
|
guards[current_guard].sleep_schedule[i]++;
|
|
}
|
|
break;
|
|
}
|
|
// print_event(&event);
|
|
}
|
|
|
|
Guard sleepiest_guard = guards[guard_numbers[0]];
|
|
int sleepiest_minute = 0;
|
|
|
|
for(int i = 0; i < 60; i++) {
|
|
for(int j = 0; j < guard_count; j++) {
|
|
Guard g = guards[guard_numbers[j]];
|
|
if (g.sleep_schedule[i] > sleepiest_guard.sleep_schedule[sleepiest_minute]) {
|
|
sleepiest_guard = g;
|
|
sleepiest_minute = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
return sleepiest_minute * sleepiest_guard.number;
|
|
}
|
|
|
|
int main() {
|
|
char *input_file_path = "../data/2018/4/input.txt";
|
|
FILE *input = fopen(input_file_path, "r");
|
|
if (input == NULL) {
|
|
printf("Can't open file %s\n", input_file_path);
|
|
return 1;
|
|
}
|
|
|
|
printf("Part 1: %d\n", part_1(input));
|
|
printf("Part 2: %d\n", part_2(input));
|
|
fclose(input);
|
|
}
|