AoC2024/5/main.c
2024-12-08 16:11:17 +01:00

139 lines
3.5 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 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);
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);
}