QUOTE: Never too old to chase dreams.

aoc

Advent of Code challenges

main.c (2767B)


      1#include <stdio.h>
      2#include <stdlib.h>
      3#include <string.h>
      4#include <dlfcn.h>
      5#include <time.h>
      6#include <wchar.h>
      7
      8typedef struct {
      9  char *uid;
     10  void *handle;
     11  long (*perform)(char *data);
     12} task_t;
     13
     14char *load_data(char *task_uid) {
     15  // convert YEAR_MT_ST to YEAR_MT
     16  int task_uid_len = strlen(task_uid);
     17  int idx = 0;
     18  for (int i = 0; i < task_uid_len; i++) {
     19    char c = task_uid[i];
     20    if (c == '_') {
     21      idx = i;
     22    }
     23  }
     24  char task_uid_base[idx + 1];
     25  snprintf(task_uid_base, idx + 1, "%s", task_uid);
     26  char filename[100];
     27  snprintf(filename, 100, "txt/%s.txt", task_uid_base);
     28  FILE *fp = fopen(filename, "r");
     29  if (fp == NULL) {
     30    return NULL;
     31  }
     32  fseek(fp, 0, SEEK_END);
     33  int len = ftell(fp);
     34  fseek(fp, 0, SEEK_SET);
     35  char *data = calloc(len + 1, sizeof(char));
     36  fread(data, sizeof(char), len, fp);
     37  data[len] = '\0';
     38  return data;
     39}
     40
     41void load_task(task_t *task, char *task_uid) {
     42  task->uid = task_uid;
     43  char cmd[100];
     44  snprintf(cmd, 100, "cc -shared -fPIC -o %s.so -Werror -Wextra -Wall -lm -pedantic src/tasks/aoc_%s.c", task_uid, task_uid);
     45  FILE *fp = popen(cmd, "r");
     46  if (fp == NULL) {
     47    return;
     48  }
     49  pclose(fp);
     50  char filename[100];
     51  snprintf(filename, 100, "./%s.so", task_uid);
     52  task->handle = dlopen(filename, RTLD_LAZY);
     53  if (task->handle == NULL) {
     54    printf("Error: failed to load task %s!\n%s\n", task_uid, dlerror());
     55    return;
     56  }
     57  task->perform = dlsym(task->handle, "perform");
     58  char *err = dlerror();
     59  if (err != 0) {
     60    printf("Error: failed to link task function %s!\n%s\n", task_uid, err);
     61    return;
     62  }
     63}
     64
     65void unload_task(task_t *task) {
     66  if (task == NULL || task->handle == NULL) {
     67    return;
     68  }
     69  dlclose(task->handle);
     70  char cmd[100];
     71  snprintf(cmd, 100, "rm %s.so", task->uid);
     72  FILE *fp = popen(cmd, "r");
     73  if (fp == NULL) {
     74    return;
     75  }
     76  pclose(fp);
     77}
     78
     79int main(int argc, char **argv) {
     80  if (argc < 2) {
     81    printf("Error: Usage: aoc <task-id>\n");
     82    return 1;
     83  }
     84  char *task_uid = argv[1];
     85  task_t task = { NULL, NULL, NULL };
     86  load_task(&task, task_uid);
     87  if (task.handle == NULL) {
     88    return 1;
     89  }
     90  char *data = load_data(task_uid);
     91  printf("task_uid: %s\n", task_uid);
     92  struct timespec time_set;
     93  clock_gettime(CLOCK_MONOTONIC, &time_set);
     94  long result = task.perform(data);
     95  struct timespec time_end;
     96  clock_gettime(CLOCK_MONOTONIC, &time_end);
     97  unload_task(&task);
     98  if (data != NULL) {
     99    free(data);
    100  }
    101  long dur_sec = time_end.tv_sec - time_set.tv_sec;
    102  long dur_ns = time_end.tv_nsec - time_set.tv_nsec;
    103  long dur_ms = dur_ns / 1000000;
    104  long dur_ys = (dur_ns / 1000) % 1000;
    105  dur_ns = dur_ns % 1000;
    106  printf("time: %lds %ldms %ldµs %ldns\n", dur_sec, dur_ms, dur_ys, dur_ns);
    107  printf("result: %ld\n", result);
    108  return 0;
    109}