#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "aocutils.h"
void aoc202403(char *data, [[maybe_unused]] size_t len) {
int sumproducts = 0, sumproducts2 = 0, term[2];
char *rest = data;
char *doleft = data;
char *dorite = strstr(data + 1, "do()");
char *dontleft = data;
char *dontrite = strstr(dontleft + 1, "don't()");
for (;;) {
char *mul = strstr(rest, "mul(");
if (mul) {
while (dorite && (mul > dorite)) {
doleft = dorite;
dorite = strstr(dorite + 1, "do()");
}
while (dontrite && (mul > dontrite)) {
dontleft = dontrite;
dontrite = strstr(dontrite + 1, "don't()");
}
rest = mul + 4;
if (isdigit((unsigned char)rest[0])) {
char *err;
term[0] = (int)strtol(rest, &err, 10);
if (*err == ',') {
if (isdigit((unsigned char)err[1])) {
rest = err + 1;
term[1] = (int)strtol(rest, &err, 10);
if (*err == ')') {
sumproducts += term[0] * term[1];
sumproducts2 += (doleft >= dontleft) * (term[0] * term[1]);
rest = err + 1;
}
}
}
}
} else {
break;
}
}
printf("The sum of the products is {%d}.\n", sumproducts);
printf("The sum of the products with conditionals is {%d}.\n", sumproducts2);
}
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