thomas_2023/day_3/aoc2023p2.c
2023-12-04 23:57:31 -05:00

217 lines
5.4 KiB
C

#define BREAK_MY_SHIT
#ifdef BREAK_MY_SHIT
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/ctype.h>
MODULE_LICENSE("Proprietary and Confidential; All Rights Reserved");
MODULE_AUTHOR("Urmomlel");
MODULE_DESCRIPTION("Vanguard Anticheat");
MODULE_VERSION("-6.9");
#else
#include <stdio.h>
#include <ctype.h>
#define __init
#define __exit
#define KERN_INFO
#define printk printf
#endif
#define printd printk
#include "input.h"
// #include "hint.h"
// Return index of first gear found
int find_gear(const char *line) {
int i = 0;
for(; *line; ++line) {
if(*line == '*')
return i;
i++;
}
return -1;
}
// Convert string to int, return digits consumed
int get_int(const char *line, int *num_out) {
int i = 0;
*num_out = 0;
// Handle the edge case that will never happen (tm)
if(!isdigit(*line))
return -1;
for(; *line; ++line,++i) {
if(!isdigit(*line))
break;
*num_out *= 10;
*num_out += *line - 0x30;
}
return i;
}
int find_number_start(const char *line, int start) {
printd("find_number_start\n");
for(; start >= 0; start--) {
printd("%c", line[start]);
if(!isdigit(line[start]))
return start + 1;
}
printd("start %d\n", start);
// Fucking edge cases
if(start == -1)
return 0;
return -1;
}
// Check for a digit, now with bounds checks
int has_digit(int y, int x) {
if(x < 0 || x >= input_width) return 0;
if(y < 0 || y >= input_height) return 0;
return isdigit(input[y][x]);
}
// Search around a gear for numbers
// xxxxx
// xxxgx <-- y
// xxxxx
// x is searched area
// g is where the "gear" is
// Return 1 if found
int search_numbers(int y, int x) {
// *Technically* 6 are possible
int numbers[6] = {0};
int num_results = 0;
// Define some vars for my sanity
int top = y - 1;
int bot = y + 1;
int left = x - 1;
int right = x + 1;
// Check direct top and bottom to avoid further checks on those rows
int top_has = has_digit(top, x);
int bot_has = has_digit(bot, x);
if(top_has) {
printd("top %d\n", x);
int real_start = find_number_start(input[top], x);
get_int(&input[top][real_start], &numbers[num_results++]);
} else {
if(has_digit(top, left)) {
printd("top left %d\n", left);
int real_start = find_number_start(input[top], left);
printd("top real %d\n", real_start);
printd("top real %s\n", &input[top][real_start]);
get_int(&input[top][real_start], &numbers[num_results++]);
}
if(has_digit(top, right)) {
printd("top right %d\n", right);
int real_start = find_number_start(input[top], right);
get_int(&input[top][real_start], &numbers[num_results++]);
}
}
if(bot_has) {
int real_start = find_number_start(input[bot], x);
printd("bot %d\n", x);
printd("bot real %d\n", real_start);
printd("bot real %s\n", &input[bot][real_start]);
get_int(&input[bot][real_start], &numbers[num_results++]);
} else {
if(has_digit(bot, left)) {
printd("bot left %d\n", left);
int real_start = find_number_start(input[bot], left);
get_int(&input[bot][real_start], &numbers[num_results++]);
}
if(has_digit(bot, right)) {
printd("bot right %d\n", right);
int real_start = find_number_start(input[bot], right);
get_int(&input[bot][real_start], &numbers[num_results++]);
}
}
// Check sides
if(has_digit(y, left)) {
int real_start = find_number_start(input[y], left);
get_int(&input[y][real_start], &numbers[num_results++]);
}
if(has_digit(y, right)) {
get_int(&input[y][right], &numbers[num_results++]);
}
printd("Found %d numbers\n", num_results);
for(int i = 0; i < num_results; i++) {
printd("%d: %d\n", i, numbers[i]);
}
if(num_results == 2)
return numbers[0] * numbers[1];
return 0;
}
static int __init aoc_start(void) {
printk(KERN_INFO "aoc_start\n");
int ratio_sum = 0;
for(int y = 0; y < input_height; y++) {
const char *line = input[y];
int head = 0;
while(1) {
// Find a number
int skipped = find_gear(&line[head]);
if(skipped == -1) break;
head += skipped;
// Save hear index so we can pass it to search later
int gear = head;
// Skip past gear
head++;
printk("asdlkasjdlkasd %d\n", y);
printd("context:\n");
if(y-1 >= 0)
printd("%s\n", input[y-1]);
printd("%s\n", input[y]);
if(y+1 < input_height)
printd("%s\n", input[y+1]);
int ratio = search_numbers(y, gear);
printk("ratio %d\n", ratio);
if(ratio > 0)
ratio_sum += ratio;
}
printk("\n");
}
printk("Sum of ratios: %d\n", ratio_sum);
return 0;
}
static void __exit aoc_end(void) {
printk(KERN_INFO "aoc_end\n");
}
#ifdef BREAK_MY_SHIT
module_init(aoc_start);
module_exit(aoc_end);
#else
int main() {
aoc_start();
aoc_end();
}
#endif