Files
adventofcode2022/day13/order.c
Dobos Ádám 51473b1352 Day13
2022-12-17 23:59:47 +01:00

246 lines
6.0 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 256
#define MAX_MEMBERS 64
#define MAX_PACKETS 512
enum NodeType {
NUMBER,
LIST
};
enum orderType {
INORDER,
OUTOFORDER,
INDECISIVE
};
typedef struct node {
enum NodeType type;
struct node *members[MAX_MEMBERS];
int member_count;
long value;
int marker;
} NODE;
void destructNode(NODE*);
long yeetList(NODE*, char*);
enum orderType inOrder(NODE*, NODE*);
void quicksort(NODE *[], int, int);
void swap(NODE *[], int, int);
int main() {
char buf[BUFFER_SIZE], *p, c;
memset(buf, 0, BUFFER_SIZE);
p = buf;
int isLeft = 1, iter = 0, sum = 0;
NODE *left, *right, *curr;
NODE *packets[MAX_PACKETS];
int packet_count = 0;
while ((c = getchar()) != EOF) {
*p++ = c;
if (c == '\n') {
if (buf[0] == '\n') {
// Empty lines don't matter
memset(buf, 0, BUFFER_SIZE);
p = buf;
continue;
}
// The root Node is always a list
if (isLeft) {
left = (NODE*)malloc(sizeof(NODE));
memset(left, 0, sizeof(NODE));
left->type = LIST;
left->marker = 0;
curr = left;
isLeft = 0;
} else {
right = (NODE*)malloc(sizeof(NODE));
memset(right, 0, sizeof(NODE));
right->type = LIST;
right->marker = 0;
curr = right;
isLeft = 1;
}
// Parse node
yeetList(curr, buf+1);
packets[packet_count] = curr;
packet_count++;
if (isLeft == 1) {
iter++;
// Compare
if (inOrder(left, right) == INORDER) {
sum += iter;
}
}
memset(buf, 0, BUFFER_SIZE);
p = buf;
}
}
printf("%i\n", sum);
// Add the two extra packets
curr = (NODE*)malloc(sizeof(NODE));
memset(curr, 0, sizeof(NODE));
curr->type = LIST;
curr->marker = 1;
yeetList(curr, "[2]]");
packets[packet_count] = curr;
packet_count++;
curr = (NODE*)malloc(sizeof(NODE));
memset(curr, 0, sizeof(NODE));
curr->type = LIST;
curr->marker = 1;
yeetList(curr, "[6]]");
packets[packet_count] = curr;
packet_count++;
// Quicksort packets
quicksort(packets, 0, packet_count - 1);
int product = 1;
for (int i = 0; i < packet_count; i++) {
if (packets[i]->marker) {
product *= i + 1;
}
// Cleanup
destructNode(packets[i]);
free(packets[i]);
}
printf("%i\n", product);
}
void destructNode(NODE* node) {
if (node->type == LIST) {
for (int i = 0; i < node->member_count; i++) {
destructNode(node->members[i]);
free(node->members[i]);
}
}
}
long yeetList(NODE* parent, char* p) {
long tmp;
char *q = p;
while(*q != ']') {
// New list
if (*q == '[') {
NODE *newNode = (NODE*)malloc(sizeof(NODE));
memset(newNode, 0, sizeof(NODE));
newNode->type = LIST;
parent->members[parent->member_count] = newNode;
parent->member_count++;
tmp = yeetList(newNode, q+1);
// Jump to the end
q += tmp + 2;
// Move one up if it is ','
if (*q == ',') {
q++;
}
} else {
// Read next int
sscanf(q, "%li", &tmp);
NODE *newNode = (NODE*)malloc(sizeof(NODE));
memset(newNode, 0, sizeof(NODE));
newNode->type = NUMBER;
newNode->value = tmp;
parent->members[parent->member_count] = newNode;
parent->member_count++;
// Move pointer to the next ',' or ']'
while (*q != ',' && *q != ']') { q++; }
// Move one up if it is ','
if (*q == ',') {
q++;
}
}
}
return q-p;
}
enum orderType inOrder(NODE* left, NODE* right) {
// If both are numbers
if (left->type == NUMBER && right->type == NUMBER) {
if (left->value < right->value) {
return INORDER;
} else if (left->value == right->value) {
return INDECISIVE;
} else {
return OUTOFORDER;
}
}
// If both are lists
if (left->type == LIST && right->type == LIST) {
for (int i = 0; i < left->member_count; i++) {
// Right ran out first
if (i == right->member_count) {
return OUTOFORDER;
}
enum orderType result = inOrder(left->members[i], right->members[i]);
if (result == INORDER || result == OUTOFORDER) return result;
}
// Left ran out first
if (right->member_count > left->member_count) return INORDER;
return INDECISIVE;
}
NODE tmp;
// If left is a number, right is a list
if (left->type == NUMBER && right->type == LIST) {
tmp.type = LIST;
tmp.members[0] = left;
tmp.member_count = 1;
return inOrder(&tmp, right);
}
// Left is a list, right is a number
tmp.type = LIST;
tmp.members[0] = right;
tmp.member_count = 1;
return inOrder(left, &tmp);
}
void quicksort(NODE *packets[], int left, int right) {
int last;
if (left >= right) {
return;
}
swap(packets, left, (left+right)/2);
last = left;
for (int i = left+1; i <= right; i++) {
if (inOrder(packets[left], packets[i]) == OUTOFORDER) {
swap(packets, ++last, i);
}
}
swap(packets, left, last);
quicksort(packets, left, last - 1);
quicksort(packets, last + 1, right);
}
void swap(NODE *packets[], int i, int j) {
NODE *tmp;
tmp = packets[i];
packets[i] = packets[j];
packets[j] = tmp;
}