#include <ctype.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "aocdailies.h" #include "aocutils.h" struct LampGrid { unsigned lit:1; unsigned bright:31; }; static void gridchange(struct LampGrid *grid, int v, unsigned r1, unsigned c1, unsigned r2, unsigned c2) { unsigned firstrow = (r1 < r2) ? r1 : r2; unsigned lastrow = (r1 < r2) ? r2 : r1; unsigned firstcol = (c1 < c2) ? c1 : c2; unsigned lastcol = (c1 < c2) ? c2 : c1; for (unsigned row = firstrow; row <= lastrow; row++) { for (unsigned col = firstcol; col <= lastcol; col++) { size_t index = 1000*row + col; switch (v) { default: fprintf(stderr, "bad value detected\n"); exit(EXIT_FAILURE); // break; // never reached case -1: grid[index].lit = 0; if (grid[index].bright > 0) grid[index].bright -= 1; break; case 1: grid[index].lit = 1; grid[index].bright += 1; break; case 2: grid[index].lit = 1 - grid[index].lit; grid[index].bright += 2; break; } } } } void aoc201506(char *data, size_t len) { (void)len; // unused argument struct LampGrid *grid_ptr = calloc(1000 * 1000, sizeof *grid_ptr); char *line = strtok(data, "\n"); while (line) { unsigned x1, x2, y1, y2; char *err = line; while (!isdigit((unsigned char)*err)) err++; y1 = strtoul(err, &err, 10); err++; x1 = strtoul(err, &err, 10); while (!isdigit((unsigned char)*err)) err++; y2 = strtoul(err, &err, 10); err++; x2 = strtoul(err, &err, 10); if (line[6] == 'n') gridchange(grid_ptr, 1, y1, x1, y2, x2); if (line[6] == 'f') gridchange(grid_ptr, -1, y1, x1, y2, x2); if (line[6] == ' ') gridchange(grid_ptr, 2, y1, x1, y2, x2); line = strtok(NULL, "\n"); } unsigned lit = 0, brightness = 0; for (unsigned row = 0; row < 1000; row++) { for (unsigned col = 0; col < 1000; col++) { lit += grid_ptr[1000*row + col].lit; brightness += grid_ptr[1000*row + col].bright; } } free(grid_ptr); printf("After following the instructions, there are %u lights lit.\n", lit); printf("Total brightness is {%u}.\n", brightness); } void aoc201505(char *data, size_t len) { (void)len; // unused argument unsigned nice = 0, nice2 = 0; char *line = strtok(data, "\n"), *curr; while (line) { unsigned vowels = 0; bool twice = false; bool hasab, hascd, haspq, hasxy; bool pair = false, hugged = false; // Part Two curr = line; if (strchr("aeiou", *curr)) vowels++; if (curr[0] == curr[1]) twice = true; for (curr = line + 1; *curr; curr++) { if (strchr("aeiou", *curr)) vowels++; if (curr[0] == curr[1]) twice = true; if (curr[-1] == curr[1]) hugged = true; char pp[3] = {curr[-1], curr[0], 0}; if (strstr(curr + 1, pp)) pair = true; } hasab = (strstr(line, "ab") != NULL); hascd = (strstr(line, "cd") != NULL); haspq = (strstr(line, "pq") != NULL); hasxy = (strstr(line, "xy") != NULL); if ((vowels >= 3) && twice && !hasab && !hascd && !haspq && !hasxy) { nice++; } if (pair && hugged) nice2++; line = strtok(NULL, "\n"); } printf("There are %u nice strings.\n", nice); printf("There are %u nice strings under the new rules.\n", nice2); } void aoc201504(char *data, size_t len) { data[--len] = 0; // remove newline, adjust `len` char longkey[128]; unsigned extra = 1; for (;;) { sprintf(longkey, "%s%u", data, extra); unsigned char tmp[16]; md5mini(tmp, longkey); if ((tmp[0] == 0) && (tmp[1] == 0) && (tmp[2] < 16)) break; extra++; } printf("Follow your key with %u to obtain five zeroes\n", extra); for (;;) { sprintf(longkey, "%s%u", data, extra); unsigned char tmp[16]; md5mini(tmp, longkey); if ((tmp[0] == 0) && (tmp[1] == 0) && (tmp[2] == 0)) break; extra++; } printf("Follow your key with %u to obtain six zeroes\n", extra); } struct House { int row, col; }; void aoc201503(char *data, size_t len) { (void)len; // unused argument char *data2 = data; // save it struct House *house = malloc(512 * sizeof *house); // assume it worked unsigned mhouse = 512, nhouse = 1; house[0].row = house[0].col = 0; // house at [0, 0] visited int x = 0, y = 0; while (*data) { switch (*data) { default: break; case '^': y++; break; case 'v': y--; break; case '>': x++; break; case '<': x--; break; } data++; bool visited = false; for (size_t k = 0; k < nhouse; k++) { if ((house[k].row == x) && (house[k].col == y)) { visited = true; break; } } if (!visited) { if (nhouse == mhouse) { // grow the array (by golden ratio) struct House *tmp = realloc(house, (13*mhouse) / 8 * sizeof *house); if (!tmp) { fprintf(stderr, "no memory. program aborted\n"); exit(EXIT_FAILURE); } house = tmp; mhouse = (13*mhouse) / 8; } house[nhouse].row = x; house[nhouse].col = y; nhouse += 1; } } printf("Santa delivered at least 1 present to %u houses.\n", nhouse); // reuse house array for part 2; don't worry about its contents nhouse = 1; // house at [0, 0] still visited :) struct House p[2] = {0}; // coordinates of santa and bot int who = 0; // 0: santa; 1: santa bot // go around from the beginning while (*data2) { switch (*data2) { default: break; case '^': p[who].row++; break; case 'v': p[who].row--; break; case '>': p[who].col++; break; case '<': p[who].col--; break; } data2++; bool visited = false; for (size_t k = 0; k < nhouse; k++) { if ((house[k].row == p[who].row) && (house[k].col == p[who].col)) { visited = true; break; } } if (!visited) { if (nhouse == mhouse) { // grow the array (by golden ratio) struct House *tmp = realloc(house, (13*mhouse) / 8 * sizeof *house); if (!tmp) { fprintf(stderr, "no memory. program aborted\n"); exit(EXIT_FAILURE); } house = tmp; mhouse = (13*mhouse) / 8; } house[nhouse].row = p[who].row; house[nhouse].col = p[who].col; nhouse += 1; } who = 1 - who; // santa; bot; santa; bot; ..., ..., ... } free(house); printf("Santa and santa bot delivered at least 1 present to %u houses.\n", nhouse); } void aoc201502(char *data, size_t len) { (void)len; // unused argument unsigned sqf = 0, f = 0; for (;;) { char *err; unsigned l = strtoul(data, &err, 10); if (*err == 0) break; data = err + 1; // skip 'x' unsigned w = strtoul(data, &err, 10); data = err + 1; // skip 'x' unsigned h = strtoul(data, &err, 10); data = err + 1; // skip newline unsigned lw = l * w; unsigned wh = w * h; unsigned hl = h * l; unsigned m = min3u(lw, wh, hl); sqf += 2*(lw + wh + hl) + m; unsigned M = max3u(l, w, h); unsigned feet = 2*(l+w+h - M) + l*h*w; f += feet; } printf("The elves need %u square feet of paper.\n", sqf); printf("The elves need %u feet of ribbon.\n", f); } void aoc201501(char *data, size_t len) { (void)len; // unused argument int floor = 0, basementsteps = -1; char *ddata = data; // save start while (*data) { if (*data == '(') floor++; else if (*data == ')') floor--; data++; // if entered the basement, part 2 done if (floor == -1) { basementsteps = data - ddata; // steps taken break; } } // continue with no regard to basement while (*data) { if (*data == '(') floor++; else if (*data == ')') floor--; data++; } printf("Santa is taken to floor {%d}.\n", floor); printf("Santa first goes to the basement at step {%d}.\n", basementsteps); }