157 lines
3.8 KiB
C
157 lines
3.8 KiB
C
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <stdbool.h>
|
||
|
|
||
|
#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);
|
||
|
}
|