Advent of Code

Artifact [c8bfebc223]
Login

Artifact [c8bfebc223]

Artifact c8bfebc223d3bbde9d49b9d342406fc5c3624bc06cdfb9e9e198b8169df266cf:


#include <ctype.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "aocdailies.h"
#include "aocutils.h"

#if 0
/* === aocYYYYDD =======================================================
===================================================================== */
void aocYYYYDD(char *data, size_t len) {
    (void)len; // unused arguments
    (void)data;
}

#endif

/* === aoc202511 =======================================================
===================================================================== */
void aoc202511(char *data, size_t len) {
    (void)len; // unused arguments
    (void)data;
}

/* === aoc202510 =======================================================
===================================================================== */
void aoc202510(char *data, size_t len) {
    (void)len; // unused arguments
    (void)data;
}

/* === aoc202509 =======================================================
===================================================================== */
struct iCoords {
    int row, col;
};

void aoc202509(char *data, size_t len) {
    (void)len; // unused argument
    struct iCoords p[512] = {0};
    char *err = data;
    int k = 0;
    while (*err) {
        p[k].row = strtol(err, &err, 10);
        if (*err != ',') break;
        err++;
        p[k++].col = strtol(err, &err, 10);
    }
    long long max_area = 0;
    for (int i = 0; i < k; i++) {
        for (int j = i + 1; j < k; j++) {
            long long area = (abs(p[i].col - p[j].col) + 1LL)
                           * (abs(p[i].row - p[j].row) + 1LL);
            if (area > max_area) max_area = area;
        }
    }
    printf("P1: %lld\n", max_area);
}

/* === aoc202508 =======================================================
===================================================================== */
void aoc202508(char *data, size_t len) {
    (void)data; // unused argument
    (void)len; // unused argument
}

/* === aoc202507 =======================================================
===================================================================== */
static unsigned tachyon_splits(struct RectangularMap *rm) {
    unsigned count = 0;
    for (int row = 0; row < rm->rows; row++) {
        for (int col = 0; col < rm->cols; col++) {
            char cc = RMcharat(rm, col, row);
            if ((cc == 'S') || (cc == '|')) {
                char *pc = RMcharptr(rm, col, row+1);
                if (pc == NULL) continue;
                if (*pc == '.') {
                    *pc = '|';
                } else if (*pc == '^') {
                    *(pc - 1) = *(pc + 1) = '|';
                    count++;
                } else if (*pc == '|') {
                    /* do nothing */
                } else {
                    /* do nothing */
                }
            }
        }
    }
    return count;
}

void aoc202507(char *data, size_t len) {
    (void)len; // unused argument
    struct RectangularMap rm[1] = {0};
    while (*data) {
        char *data2 = data;
        while (*data != '\n') data++;
        *data = 0; // erase newline
        RMaddline(rm + 0, data2);
        *data++ = '\n'; // unerase newline (obviously!) and skip it
    }
    unsigned part1 = tachyon_splits(rm);
    printf("P1: %u\n", part1);
    RMfree(rm);
}

/* === aoc202506 =======================================================
===================================================================== */
static long long unsigned add2506(long long unsigned v[4][1024], int lin, int col) {
    long long unsigned sum = 0;
    for (int k = 0; k < lin; k++) sum += v[k][col];
    return sum;
}
static long long unsigned mul2506(long long unsigned v[4][1024], int lin, int col) {
    long long unsigned sum = 1;
    for (int k = 0; k < lin; k++) sum *= v[k][col];
    return sum;
}

static long long unsigned input_202506[4][1024];
void aoc202506(char *data, size_t len) {
    (void)len; // unused argument
    char *X;
    for (;;) {
        X = strchr(data, '\n');
        if (!X) break;
        *X = 'X';
    }
    int lin = 0, col;
    char *err = data;
    for (;;) { // for each line
        col = 0;
        for (;;) { // for each number
            while (isspace(*err)) err++;
            long long unsigned tmp = strtoull(err, &err, 10);
            if ((*err == 'X') && (tmp == 0)) { err++; break; }
            input_202506[lin][col++] = tmp;
        }
        lin++;
        printf("got line %d with %d columns\n", lin, col);
        if ((*err == '+') || (*err == '*')) break;
    }
    printf("from %llu to %llu\n", input_202506[0][0], input_202506[lin-1][col-1]);
    col = 0;
    while (isspace(*err)) err++;
    long long unsigned sum = 0;
    for (;;) {
        switch (*err) {
            default: /* does not happen! */ break;
            case 'X': break;
            case '+': sum += add2506(input_202506, lin, col); break;
            case '*': sum += mul2506(input_202506, lin, col); break;
        }
        if (*err == 'X') break;
        col++;
        err++;
        while (isspace(*err)) err++;
    }
    printf("part 1: %llu\n", sum);
}

/* === aoc202505 =======================================================
===================================================================== */
struct Range {
    long long unsigned lo, hi;
};

static int ascending(const void *a, const void *b) {
    const struct Range *aa = a, *bb = b;
    if (aa->lo < bb->lo) return -1;
    if (aa->lo > bb->lo) return 1;
    return 0;
}

void aoc202505(char *data, size_t len) {
    (void)len; // unused argument
    struct Range r[200] = {0};
    size_t nr = 0;
    char *err;
    for (;;) {
        // read ranges
        char *minus = strchr(data, '-');
        if (!minus) break;
        *minus = 0;
        r[nr].lo = strtoull(data, &err, 10);
        *minus++ = '-';
        char *enter = strchr(minus, '\n');
        *enter = 0;
        r[nr++].hi = strtoull(minus, &err, 10);
        *enter++ = '\n';
        data = enter;
    }
    unsigned fresh = 0;
    for (;;) {
        // read and process single entries
        long long unsigned item = strtoull(data, &err, 10);
        if (err[0] != '\n') break;
        data = err + 1;
        for (size_t k = 0; k < nr; k++) {
            if ((r[k].lo <= item) && (item <= r[k].hi)) {
                fresh++;
                break;
            }
        }
    }
    printf("There are %u fresh items.\n", fresh);

    qsort(r, nr, sizeof *r, ascending);
    #if 0
    for (;;) {
        int mergecount = 0;
        for (size_t k = 1; k < nr, k++) {
            for (size_t kk = 0; kk < k; kk++) {
                mergecount += merge(r, kk, k) {
                    mergecount++;
                    nr--;
                }
            }
        }
        if (mergecount == 0) break;
    }
    #endif
}

/* === aoc202504 =======================================================
===================================================================== */
static unsigned evolve(struct RectangularMap *rm, unsigned src) {
    unsigned changes = 0;
    unsigned dst = 1 - src;
    for (int row = 0; row < rm->rows; row++) {
        for (int col = 0; col < rm->cols; col++) {
            char cc = RMcharat(rm + src, col, row);
            char *destin = RMcharptr(rm + dst, col, row);
            if (cc == '@') {
                unsigned nearby = 0;
                for (int deltarow = -1; deltarow <= 1; deltarow++) {
                    for (int deltacol = -1; deltacol <= 1; deltacol++) {
                        nearby += (RMcharat(rm + src, col+deltacol,
                                            row+deltarow) == '@');
                    }
                }
                nearby -= 1; // remove self
                if (nearby < 4) {
                    *destin = '.';
                    changes++;
                } else {
                    *destin = '@';
                }
            } else if (cc != 0) {
                *destin = '.';
            } else {
                *destin = 0; // shouldn't happen, except beyond borders
            }
        }
    }
    return changes;
}

void aoc202504(char *data, size_t len) {
    (void)len; // unused argument
    struct RectangularMap rm[2] = {0};
    while (*data) {                      // copy from data to rms
        char *data2 = data;
        while (*data != '\n') data++;
        *data = 0; // erase newline
        RMaddline(rm + 0, data2);
        RMaddline(rm + 1, data2); // set both rm's to the same thing
        *data++ = '\n'; // unerase newline (obviously!) and skip it
    }
    unsigned part1 = evolve(rm, 0); // evolve from rm[0] to rm[1]
    unsigned part2 = part1, src = 1;
    for (;;) {
        unsigned tmp = evolve(rm, src); // keep evolving
        if (tmp == 0) break; // STOP    // back and forth
        src = 1 - src;                  // between rm[1] and rm[0]
        part2 += tmp; // add changes from this round
    }
    printf("P1: %u; P2: %u\n", part1, part2);
    RMfree(rm);
    RMfree(rm + 1);
}

/* === aoc202503 =======================================================
===================================================================== */
static long long unsigned maxj(const unsigned char *b, unsigned blen, unsigned nlen) {
    if (nlen == 0) return 0;
    const unsigned char *newb = b + 1;
    unsigned newlen = blen - 1;
    unsigned localmax = 0;
    for (unsigned k = 0; k < blen - nlen + 1; k++) {
        if (b[k] > localmax) {
            localmax = b[k];
            newb = b + k + 1;
            newlen = blen - k - 1;
        }
    }
    return localmax*upow(10, nlen - 1) + maxj(newb, newlen, nlen - 1);
}

void aoc202503(char *data, size_t len) {
    (void)len; // unused argument
    long long unsigned part1 = 0, part2 = 0;
    char *p = data;
    for (;;) {
        char *pp = strchr(p, '\n');
        if (pp == NULL) break;
        unsigned char bank[256] = {0};
        unsigned banklen;
        for (banklen = 0; banklen < (unsigned)(pp - p); banklen++) {
            bank[banklen] = (unsigned)p[banklen] - '0';
        }
        part1 += maxj(bank, banklen, 2);
        part2 += maxj(bank, banklen, 12);
        p = pp + 1;
    }
    printf("parts 1 and 2: %llu %llu\n", part1, part2);
}

/* === aoc202502 =======================================================
===================================================================== */
static int extractdata(char **data, char *p1, char *p2) {
    char *d = *data;
    if (*d == ',') d++; // skip ','
    if (!isdigit(*d)) return 0;
    while (isdigit(*d)) { *p1++ = *d++; *p1 = 0; }
    if (*d != '-') { fprintf(stderr, "bad data\n"); exit(EXIT_FAILURE); }
    d++; // skip '-'
    while (isdigit(*d)) { *p2++ = *d++; *p2 = 0; }
    *data = d;
    return 1;
}

static int prepeat(int n, long long unsigned v) {
    char tmp[42];
    int len = sprintf(tmp, "%llu", v);
    if (len % n) return 0;
    if (len < 2*n) return 0;
    for (int k = 0; k+n < len; k++) {
        if (tmp[k] != tmp[k+n]) return 0;
    }
    return 1;
}

static long long unsigned suminvalid2(const char *start, const char *finis) {
    long long unsigned retval = 0;
    long long unsigned pstart = 0, pfinis = 0;
    int k = 0;
    while (start[k]) {
        pstart *= 10; pstart += (unsigned)start[k] - '0';
        k++;
    }
    k = 0;
    while (finis[k]) {
        pfinis *= 10; pfinis += (unsigned)finis[k] - '0';
        k++;
    }
    for (long long unsigned kk = pstart; kk <= pfinis; kk++) {
        if (prepeat(1, kk)) retval += kk;
        else if (prepeat(2, kk)) retval += kk;
        else if (prepeat(3, kk)) retval += kk;
        else if (prepeat(4, kk)) retval += kk;
        else if (prepeat(5, kk)) retval += kk;
        else if (prepeat(6, kk)) retval += kk;
        else if (prepeat(7, kk)) retval += kk;
        else if (prepeat(8, kk)) retval += kk;
        else if (prepeat(9, kk)) retval += kk;
    }
    return retval;
}

static long long unsigned suminvalid(const char *start, const char *finis) {
    long long unsigned pstart = 0, pfinis = 0;
    int k = 0;
    while (start[k]) {
        pstart *= 10; pstart += (unsigned)start[k] - '0';
        pfinis *= 10; pfinis += (unsigned)finis[k] - '0';
        k++;
    }
    long long unsigned lo = pstart / upow(10, (unsigned)(k/2));
    long long unsigned hi = pfinis / upow(10, (unsigned)(k/2));
    long long unsigned retval = 0;
    for (long long unsigned kk = lo; kk <= hi; kk++) {
        long long unsigned val = kk*upow(10, (unsigned)(k/2)) + kk;
        if ((pstart <= val) && (val <= pfinis)) retval += val;
    }
    return retval;
}

void aoc202502(char *data, size_t len) {
    (void)len; // unused argument
    long long unsigned part1 = 0;
    long long unsigned part2 = 0;
    char start[42], finis[42];
    while (extractdata(&data, start, finis)) {
        int lenstart = strlen(start);
        int lenfinis = strlen(finis);
        part2 += suminvalid2(start, finis);
        if (lenstart != lenfinis) {
            char tmp[42];
            if (lenfinis % 2) {
                sprintf(tmp, "%llu", upow(10, (unsigned)lenstart) - 1);
                part1 += suminvalid(start, tmp);
            } else {
                sprintf(tmp, "%llu", upow(10, (unsigned)lenstart));
                part1 += suminvalid(tmp, finis);
            }
        } else {
            if (lenstart % 2) {
                part1 += 0;
            } else {
                part1 += suminvalid(start, finis);
            }
        }
    }
    printf("parts 1 and 2: %llu %llu\n", part1, part2);
}

/* === aoc202501 =======================================================
===================================================================== */
static int zeroaccum(int start, char d, int v, int *p1, int *p2) {
    int direction;
    switch (d) {
        default: fprintf(stderr, "Invalid letter: %c\n", d);
                 exit(EXIT_FAILURE);
        case 'R': direction = 1;
                  break;
        case 'L': direction = -1;
                  break;
    }
    while (v--) {
        start += direction;
        if (start == -1) start = 99;
        if (start == 100) start = 0;
        if (start == 0) *p2 += 1;
    }
    if (start == 0) *p1 += 1;
    return start;
}

void aoc202501(char *data, size_t len) {
    (void)len; // unused argument
    int pos = 50;
    int part1 = 0, part2 = 0;
    char dir; int value;
    while (*data) {
        dir = *data++;
        value = 0;
        while (isdigit(*data)) {
            value *= 10;
            value += *data - '0';
            data++;
        }
        while (isspace(*data)) data++; // skip whitespace
        pos = zeroaccum(pos, dir, value, &part1, &part2);
    }

    // part1
    printf("password for part1 is %d\n", part1);

    // part2
    printf("password for part2 is %d\n", part2);
}