#include #include #include #include #define LINES 1000 struct page { int page; int *illegalPrec; int ruleLen; struct page *next; }; void shuffle(int *array, size_t n) { if (n > 1) { size_t i; for (i = 0; i < n - 1; i++) { size_t j = i + rand() / (RAND_MAX / (n - i) + 1); int t = array[j]; array[j] = array[i]; array[i] = t; } } } void add_page(struct page *head, int page) { // traverse list until last member while(head->next) head = head->next; // allocate and store ptr head->next = malloc(sizeof(struct page)); // allocate illegalArray head->next->illegalPrec = calloc(16, sizeof(int)); head->next->ruleLen = 16; // store page number in new item head->next->page = page; head->next->next = 0; } void add_rule (struct page *page, int illegal) { // make sure you wont go oob int i = 0; for (i = 0; i < page->ruleLen && page->illegalPrec[i] != 0; i++); // if oob, realloc illegalPrec and change ruleLen-size if (i >= page->ruleLen - 1) { page->illegalPrec = realloc(page->illegalPrec, page->ruleLen * 2 * sizeof(int)); page->ruleLen *= 2; } // store illegal page page->illegalPrec[i] = illegal; } // power! x to the y! int pow(int x, int y) { int ans = 1; for (int i = 0; i < y; i++) ans *= x; return ans; } // parse string into array of numbers int parse_numbers(char *str_row, int *row, int n) { int i = 0; for (; str_row[i] != '\n'; i++); for (; i >= 0; i--) { int pos = 0; for (; str_row[i] >= '0' && str_row[i] <= '9' && i >= 0; i--) { row[n] += (str_row[i] - '0') * pow(10, pos); pos++; } n--; } return 1; } bool check_report (int *updates, int len, struct page *rules) { for (int i = len - 1; i >= 0; i--) { struct page *current = rules; // for each array member, try to find it in rules while (current->page != updates[i] && current->next) current = current->next; if (current->page != updates[i]) continue; // if found, for each lower array member, // iterate through current->illegalPrec // if match, illegal report for (int j = i - 1; j >= 0; j--) { for (int k = 0; k < current->ruleLen; k++) { if (updates[j] == current->illegalPrec[k]) return 0; } } } return 1; } int main () { FILE *input = fopen("input", "r"); // create list of pages, each with arrays of pages that must be BEFORE them struct page *pages = malloc(sizeof(struct page)); struct page *current = pages; // find pair. int left = 0; int right = 0; // init head fscanf(input, "%d|%d", &left, &right); current->page = left; current->ruleLen = 16; current->illegalPrec = calloc(16, sizeof(int)); add_rule(current, right); while (fscanf(input, "%d|%d", &left, &right) == 2) { // check if left exists in list while (current->next && current->page != left) current = current->next; if (current->page == left) { add_rule(current, right); } else { add_page(pages, left); add_rule(current->next, right); } current = pages; } fseek(input, -2, SEEK_CUR); // take in line. Parse numbers until newline. char line[100]; int sum_reports = 0; while (fgets(line, 100, input)) { int numbers = 1; for (int c = 0; line[c]; c++) numbers += (line[c] == ','); int *updates = (int *)calloc(numbers, sizeof(int)); parse_numbers(line, updates, numbers); while (!check_report(updates, numbers, pages)) { shuffle(updates, numbers); if (check_report(updates, numbers, pages)) sum_reports += updates[numbers / 2]; } } // Remember how many numbers you got this line, we'll iterate backwards! // for each number in update, iterate through page-rules til you find it // if found, make sure it isnt preceded by any page in its list? // probably best to work completely backwards? rules can only ban pages from being before others printf("sum: %d\n", sum_reports); }