aoc_omni/c/2018/4/problem_04.c

211 lines
5.6 KiB
C
Raw Normal View History

2025-11-30 21:22:21 -05:00
#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);
}