#include #include #include #include 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); }