Day13
This commit is contained in:
245
day13/order.c
Normal file
245
day13/order.c
Normal file
@@ -0,0 +1,245 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user