217 lines
5.4 KiB
C
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
|