#include #include #include #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; }