Browse Source

day4p1

master
mid-kid 6 years ago
parent
commit
ada5f3e2f8
  1. 12
      day4p1/Makefile
  2. 1102
      day4p1/input
  3. BIN
      day4p1/main
  4. 210
      day4p1/main.c

12
day4p1/Makefile

@ -0,0 +1,12 @@
CFLAGS := -Wall -Wextra -std=c17 -D_GNU_SOURCE
LIBS := glib-2.0
CFLAGS += $(shell pkg-config --cflags $(LIBS))
LDLIBS := $(shell pkg-config --libs $(LIBS))
.PHONY: all
all: main
.PHONY: clean
clean:
rm -f main

1102
day4p1/input

File diff suppressed because it is too large

BIN
day4p1/main

Binary file not shown.

210
day4p1/main.c

@ -0,0 +1,210 @@
#include <stdio.h>
#include <glib.h>
enum action {
ACTION_BEGIN,
ACTION_SLEEP,
ACTION_WAKE
};
struct event {
unsigned year;
unsigned month;
unsigned day;
unsigned hour;
unsigned minute;
enum action action;
unsigned guard;
};
gint compare_event(gconstpointer a, gconstpointer b)
{
#define _(x) (int)( \
(x)->year * 12 * 32 * 24 * 60 + \
(x)->month * 32 * 24 * 60 + \
(x)->day * 24 * 60 + \
(x)->hour * 60 + \
(x)->minute)
return (_((struct event *)a) - _((struct event *)b));
#undef _
}
GSList *parse_events(const char *fname)
{
FILE *f = fopen(fname, "r");
if (!f) {
perror(fname);
return NULL;
}
GSList *list = NULL;
char *line = NULL;
size_t line_len = 0;
while (getline(&line, &line_len, f) != -1) {
g_strstrip(line);
// Find the action text
char *action = line;
while (*action && *action++ != '[');
while (*action && *action++ != ']');
if (*action) *action++ = '\0'; // Expect a minimum of one space
if (!*action) {
fprintf(stderr, "Warning: ignoring '%s': No action found.\n", line);
continue;
}
g_strstrip(action);
struct event *event = g_malloc0(sizeof(struct event));
// Haha what is proper parsing
sscanf(line, "[%u-%u-%u %u:%u]",
&event->year,
&event->month,
&event->day,
&event->hour,
&event->minute
);
// Basic sanity check
if (event->month >= 12 ||
event->day >= 32 ||
event->hour >= 24 ||
event->minute >= 60) {
fprintf(stderr, "Warning: ignoring '%s': Invalid time.\n", line);
g_free(event);
continue;
}
// Figure out the action
if (strcmp(action, "falls asleep") == 0) {
event->action = ACTION_SLEEP;
} else if (strcmp(action, "wakes up") == 0) {
event->action = ACTION_WAKE;
} else {
sscanf(action, "Guard #%u begins shift", &event->guard);
if (!event->guard) continue;
}
list = g_slist_prepend(list, event);
}
free(line);
fclose(f);
// We can't do much without information about the guards
unsigned current_guard = 0;
list = g_slist_sort(list, compare_event);
for (GSList *l = list; l; l = l->next) {
struct event *event = (struct event *)l->data;
if (event->action == ACTION_BEGIN) {
current_guard = event->guard;
} else {
event->guard = current_guard;
}
}
return list;
}
unsigned find_sleepiest_guard(GSList *events)
{
// Figure out which guard has slept the most
// Assumptions:
// - All sleep/wake hours are 00
// - Every sleep action is coupled with a wake action from the same guard
// According to the puzzle these are safe assumptions to make,
// and it's not worth my time to do everything "properly" right now.
GHashTable *table = g_hash_table_new(NULL, NULL);
unsigned start_time = 0;
for (GSList *l = events; l; l = l->next) {
struct event *event = (struct event *)l->data;
if (event->action == ACTION_SLEEP) {
start_time = event->minute;
} else if (event->action == ACTION_WAKE) {
unsigned time = event->minute - start_time;
unsigned current_time = GPOINTER_TO_UINT(g_hash_table_lookup(table, GUINT_TO_POINTER(event->guard)));
current_time += time;
g_hash_table_insert(table, GUINT_TO_POINTER(event->guard), GUINT_TO_POINTER(current_time));
}
}
unsigned sleepiest_guard = 0;
unsigned sleepiest_guard_time = 0;
gpointer key, value;
GHashTableIter iter;
g_hash_table_iter_init(&iter, table);
while (g_hash_table_iter_next(&iter, &key, &value)) {
unsigned guard = GPOINTER_TO_UINT(key);
unsigned time = GPOINTER_TO_UINT(value);
printf("Guard #%u: %u minutes\n", guard, time);
if (time > sleepiest_guard_time) {
sleepiest_guard = guard;
sleepiest_guard_time = time;
}
}
g_hash_table_destroy(table);
return sleepiest_guard;
}
unsigned find_sleepiest_minute(GSList *events, unsigned guard)
{
// Figure out which is the guard's most slept minute
// Also assuming all sleep hours are at 12am
unsigned char slept[60] = {0};
unsigned start_time = 0;
for (GSList *l = events; l; l = l->next) {
struct event *event = (struct event *)l->data;
if (event->guard != guard) continue;
if (event->action == ACTION_SLEEP) {
start_time = event->minute;
} else if (event->action == ACTION_WAKE) {
for (unsigned i = start_time; i < event->minute; i++) {
if (slept[i] >= UCHAR_MAX) continue;
slept[i]++;
}
}
}
unsigned slept_minute = 0;
unsigned slept_minute_count = 0;
for (unsigned i = 0; i < 60; i++) {
if (slept[i] > slept_minute_count) {
slept_minute = i;
slept_minute_count = slept[i];
}
}
return slept_minute;
}
int main()
{
GSList *events = parse_events("input");
for (GSList *l = events; l; l = l->next) {
struct event *event = (struct event *)l->data;
printf("[%04u-%02u-%02u %02u:%02u] %u (%u)\n",
event->year, event->month, event->day,
event->hour, event->minute,
event->action, event->guard);
}
unsigned sleepiest_guard = find_sleepiest_guard(events);
printf("Sleepiest guard: %u\n", sleepiest_guard);
unsigned sleepiest_minute = find_sleepiest_minute(events, sleepiest_guard);
printf("Most slept minute: %u\n", sleepiest_minute);
printf("Result hash: %u\n", sleepiest_guard * sleepiest_minute);
g_slist_free_full(events, g_free);
return 0;
}
Loading…
Cancel
Save