ADDED aoc.c Index: aoc.c ================================================================== --- /dev/null +++ aoc.c @@ -0,0 +1,78 @@ +#include +#include +#include + +#include "aocutils.h" +#include "aocdailies.h" // prototypes for all aocYYYYdd functions! + +#define MAX_YEAR 2024 + +int main(int argc, char **argv) { + int y = 0, d = 0; + char dataname[99]; + if (argc >= 3) { + char *err; + y = (int)strtol(argv[1], &err, 10); + if (err && *err) y = 0; + if (y < 2015) y = 0; + if (y > MAX_YEAR) y = 0; + d = (int)strtol(argv[2], &err, 10); + if (err && *err) d = 0; + if (d < 1) d = 0; + if (d > 25) d = 0; + if (argc >= 4) { + sprintf(dataname, "%.98s", argv[3]); + } else { + sprintf(dataname, ".%04d%02d.txt", y, d); + } + } + if ((y == 0) || (d == 0)) { + fprintf(stderr, "syntax: %s yyyy dd [input-file]\n", argv[0]); + fprintf(stderr, " where 2015 <= yyyy <= %d\n", MAX_YEAR); + fprintf(stderr, " and 1 <= dd <= 25\n"); + fprintf(stderr, "if no [input-file] is supplied loads the file .yyyydd.txt\n"); + exit(EXIT_FAILURE); + } + // read data from dataname into input + char *input = NULL; + size_t ilen = slurp(&input, dataname); + + // call the right function + void (*p)(char *, size_t) = NULL; + switch (y * 100 + d) { + default: fprintf(stderr, "no function for year %d and day %d\n", y, d); + exit(EXIT_FAILURE); + #if 0 + case 201501: p = aoc201501; break; + case 201502: p = aoc201502; break; + case 201503: p = aoc201503; break; + case 201504: p = aoc201504; break; + case 201505: p = aoc201505; break; + case 201506: p = aoc201506; break; + case 201507: p = aoc201507; break; + case 201508: p = aoc201508; break; + case 201509: p = aoc201509; break; + case 201510: p = aoc201510; break; + case 201511: p = aoc201511; break; + case 201512: p = aoc201512; break; + case 201513: p = aoc201513; break; + case 201514: p = aoc201514; break; + case 201515: p = aoc201515; break; + case 201516: p = aoc201516; break; + case 201517: p = aoc201517; break; + case 201518: p = aoc201518; break; + case 201519: p = aoc201519; break; + case 201520: p = aoc201520; break; + case 201521: p = aoc201521; break; + case 201522: p = aoc201522; break; + case 201523: p = aoc201523; break; + case 201524: p = aoc201524; break; + case 201525: p = aoc201525; break; + #endif + + case 202401: p = aoc202401; break; + case 202402: p = aoc202402; break; + } + p(input, ilen); + free(input); +} ADDED aoc2024.c Index: aoc2024.c ================================================================== --- /dev/null +++ aoc2024.c @@ -0,0 +1,113 @@ +#include +#include +#include + +#include "aocutils.h" + +static int safereport(int *v, int nv) { + int dir = 1; // ascending + if (v[0] > v[1]) dir = -1; // descending + for (int k = 1; k < nv; k++) { + if (v[k-1] == v[k]) return 0; + if (abs(v[k-1] - v[k]) > 3) return 0; + if (dir == -1) { + if (v[k-1] < v[k]) return 0; + } else { + if (v[k-1] > v[k]) return 0; + } + } + return 1; +} + +static int safereportdamp(int *v, int nv) { + for (int swap = 0; swap < nv; swap++) { // abcde + int tmp = v[swap]; // swap(0, 0): a-bcde + v[swap] = v[0]; // swap(1, 0): b-acde + v[0] = tmp; // swap(2, 0): c-abde + if (safereport(v + 1, nv - 1)) return 1; // swap(3, 0): d-abce + } // ... and so on + return 0; +} + +void aoc202402(char *data, [[maybe_unused]] size_t len) { + int safe = 0, safe2 = 0; + char *line = strtok(data, "\n"); + while (line) { + int *arr = NULL; + int narr = text2array(&arr, line); + if (safereport(arr, narr)) { + safe += 1; + safe2 += 1; + } else { + safe2 += safereportdamp(arr, narr); + } + free(arr); + line = strtok(NULL, "\n"); + } + printf("There are %d safe reports.\n", safe); + printf("There are %d safe reports with the Problem Dampener.\n", safe2); +} + +static int delta(const void *a, const void *b) { + return *(const int *)a - *(const int *)b; +} + +#ifdef LISTSIZE +# error LISTSIZE already defined +#endif +#define LISTSIZE 1200 +void aoc202401(char *data, [[maybe_unused]] size_t len) { + int v1, v2; // values from data + char *err; + int list1[LISTSIZE], list2[LISTSIZE]; // the lists + int n1 = 0, n2 = 0; + while ((v1 = (int)strtol(data, &err, 10))) { // assume well-formatted data + data = err; + v2 = (int)strtoul(data, &err, 10); + data = err; + list1[n1++] = v1; // add v1 to list1 + list2[n2++] = v2; // add v2 to list2 + } + // redundant check :-) + if (n1 != n2) printf("Error: list are not the same size\n"); + + // sort the lists + qsort(list1, (size_t)n1, sizeof *list1, delta); + qsort(list2, (size_t)n2, sizeof *list2, delta); + + // part1 + int sumdeltas = 0; + for (int k = 0; k < n1; k++) { + sumdeltas += abs(list1[k] - list2[k]); + } + printf("Total distance between lists is {%d}.\n", sumdeltas); + + // part2 + int similarity = 0; + for (int k = 0; k < n1; k++) { +#if 1 // use the fact lists are sorted: complexity: O(n log n) + int leftcount = 1; // number of equal values in list1 + while ((k + leftcount < n1) && (list1[k] == list1[k + leftcount])) leftcount++; + // find list1 k'ths value in list2 + int *p = bsearch(list1 + k, list2, (size_t)n2, sizeof *list2, delta); + if (p) { + int idxl = (int)(p - list2); // search backwards and forwards in list2 + int idxr = (int)(p - list2); // for the k'th value in list1 + while ((idxl > 0) && (list2[idxl - 1] == *p)) idxl -= 1; + while ((idxr < n2 - 1) && (list2[idxr + 1] == *p)) idxr += 1; + int rightcount = idxr - idxl + 1; // number of repeats in list2 + similarity += *p * rightcount * leftcount; + } + k += leftcount - 1; // adjust loop control variable +#else + // loop inside loop: complexity O(n^2); don't care lists are sorted + int count = 0; + for (int kk = 0; kk < n2; kk++) { + if (list1[k] == list2[kk]) count++; + } + similarity += list1[k] * count; +#endif + } + printf("Similarity score between lists is {%d}.\n", similarity); +} +#undef LISTSIZE ADDED aocdailies.h Index: aocdailies.h ================================================================== --- /dev/null +++ aocdailies.h @@ -0,0 +1,35 @@ +#ifndef AOCDAILY_H_INCLUDED +#define AOCDAILY_H_INCLUDED + +#if 0 +void aoc201501(char *, size_t); +void aoc201502(char *, size_t); +void aoc201503(char *, size_t); +void aoc201504(char *, size_t); +void aoc201505(char *, size_t); +void aoc201506(char *, size_t); +void aoc201507(char *, size_t); +void aoc201508(char *, size_t); +void aoc201509(char *, size_t); +void aoc201510(char *, size_t); +void aoc201511(char *, size_t); +void aoc201512(char *, size_t); +void aoc201513(char *, size_t); +void aoc201514(char *, size_t); +void aoc201515(char *, size_t); +void aoc201516(char *, size_t); +void aoc201517(char *, size_t); +void aoc201518(char *, size_t); +void aoc201519(char *, size_t); +void aoc201520(char *, size_t); +void aoc201521(char *, size_t); +void aoc201522(char *, size_t); +void aoc201523(char *, size_t); +void aoc201524(char *, size_t); +void aoc201525(char *, size_t); +#endif + +void aoc202401(char *, size_t); +void aoc202402(char *, size_t); + +#endif ADDED aocutils.c Index: aocutils.c ================================================================== --- /dev/null +++ aocutils.c @@ -0,0 +1,119 @@ +#include +#include +#include "aocutils.h" + +int text2array(int **dst, const char *r) { + int *a = malloc(sizeof *a); + int na = 0, sa = 1; + char *err; + int v; + for (;;) { + if (na == sa) { + int *tmp = realloc(a, (size_t)(2*sa)*sizeof *tmp); + if (!tmp) exit(EXIT_FAILURE); + a = tmp; + sa *= 2; + } + v = (int)strtol(r, &err, 10); + a[na++] = v; + if (!*err) break; + r = err; + } + *dst = a; + return na; +} + +size_t slurp(char **dst, const char *fn) { + if (*dst) { + fprintf(stderr, "slurp() must be called with a pointer to void!\n"); + exit(EXIT_FAILURE); + } + FILE *h = fopen(fn, "r"); + if (!h) { + perror(fn); + exit(EXIT_FAILURE); + } + + int ch; + char *tmp = malloc(512); + size_t s = 512; + size_t r = 0; + while ((ch = fgetc(h)) != EOF) { + if (r == s) { + //grow tmp + char *ttmp = realloc(tmp, (13*s)/8); + if (ttmp) { + tmp = ttmp; + s = (13*s)/8; + } else { + free(tmp); + return 0; + } + } + tmp[r++] = (char)ch; + } + fclose(h); + *dst = tmp; + + return r; +} + +int max3(int a, int b, int c) { + if (a > b) { + if (a > c) return a; + return c; + } else { + if (b > c) return b; + } + return c; +} + +double fmax3(double a, double b, double c) { + if (a > b) { + if (a > c) return a; + return c; + } else { + if (b > c) return b; + } + return c; +} + +long max3l(long a, long b, long c) { + if (a > b) { + if (a > c) return a; + return c; + } else { + if (b > c) return b; + } + return c; +} + +int min3(int a, int b, int c) { + if (a < b) { + if (a < c) return a; + return c; + } else { + if (b < c) return b; + } + return c; +} + +double fmin3(double a, double b, double c) { + if (a < b) { + if (a < c) return a; + return c; + } else { + if (b < c) return b; + } + return c; +} + +long min3l(long a, long b, long c) { + if (a < b) { + if (a < c) return a; + return c; + } else { + if (b < c) return b; + } + return c; +} ADDED aocutils.h Index: aocutils.h ================================================================== --- /dev/null +++ aocutils.h @@ -0,0 +1,13 @@ +#ifndef AOCUTILS_H_INCLUDED +#define AOCUTILS_H_INCLUDED + +int text2array(int **dst, const char *r); +size_t slurp(char **dst, const char *filename); +int max3(int a, int b, int c); +double fmax3(double a, double b, double c); +long max3l(long a, long b, long c); +int min3(int a, int b, int c); +double fmin3(double a, double b, double c); +long min3l(long a, long b, long c); + +#endif