160 lines
3.8 KiB
C
160 lines
3.8 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
|
||
|
|
||
|
#include "input.h"
|
||
|
// #include "hint.h"
|
||
|
|
||
|
// Skip over all non numeric characters
|
||
|
// Return index of first numeric character found
|
||
|
int find_int(const char *line) {
|
||
|
int i = 0;
|
||
|
for(; *line; ++line) {
|
||
|
if(isdigit(*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;
|
||
|
}
|
||
|
|
||
|
// Search around an int for "components"
|
||
|
// x x x x x x x
|
||
|
// x [start n n n end] x <-- y
|
||
|
// x x x x x x x
|
||
|
// x is searched area
|
||
|
// [start n end] is where the "part number" is
|
||
|
// Return 1 if found
|
||
|
int search_component(int y, int start, int end) {
|
||
|
int left = start - 1;
|
||
|
int right = end + 1;
|
||
|
int top = y - 1;
|
||
|
int bottom = y + 1;
|
||
|
|
||
|
// Spot check the immediate left and right characters
|
||
|
if(left >= 0 && input[y][left] != '.') return 1;
|
||
|
if(right < input_width && input[y][right] != '.') return 1;
|
||
|
|
||
|
// Check top row
|
||
|
// We can clamp left and right now
|
||
|
if(left < 0) left = 0;
|
||
|
if(right >= input_width) right = input_width - 1;
|
||
|
|
||
|
// Check top row if it is valid
|
||
|
if(top > 0) {
|
||
|
for(int i = left; i <= right; i++)
|
||
|
if(input[top][i] != '.') return 1;
|
||
|
}
|
||
|
// Check bottom row if it is valid
|
||
|
if(bottom < input_height) {
|
||
|
for(int i = left; i <= right; i++)
|
||
|
if(input[bottom][i] != '.') return 1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int __init aoc_start(void) {
|
||
|
printk(KERN_INFO "aoc_start\n");
|
||
|
|
||
|
int part_number_count = 0;
|
||
|
|
||
|
for(int y = 0; y < input_height; y++) {
|
||
|
const char *line = input[y];
|
||
|
int head = 0;
|
||
|
while(1) {
|
||
|
// Find a number
|
||
|
printk("line[head] %s\n", &line[head]);
|
||
|
int skipped = find_int(&line[head]);
|
||
|
printk("skipped %d\n", skipped);
|
||
|
if(skipped == -1) break;
|
||
|
head += skipped;
|
||
|
// Save start index so we can pass it to search later
|
||
|
int start = head;
|
||
|
|
||
|
// Read the int
|
||
|
int number = 0;
|
||
|
printk("line[start] %s\n", &line[head]);
|
||
|
int number_num_chars = get_int(&line[head], &number);
|
||
|
if(number_num_chars < 0) {
|
||
|
printk("Bad shit happened\n");
|
||
|
return -1;
|
||
|
}
|
||
|
head += number_num_chars;
|
||
|
|
||
|
printk("number %d\n", number);
|
||
|
printk("n_number %d\n", number_num_chars);
|
||
|
|
||
|
printk("context:\n");
|
||
|
if(y-1 > 0)
|
||
|
printk("%s\n", input[y-1]);
|
||
|
printk("%s\n", input[y]);
|
||
|
if(y+1 < input_height)
|
||
|
printk("%s\n", input[y+1]);
|
||
|
int valid = search_component(y, start, head - 1);
|
||
|
printk("valid %d\n", valid);
|
||
|
|
||
|
if(valid)
|
||
|
part_number_count += number;
|
||
|
}
|
||
|
|
||
|
printk("\n");
|
||
|
}
|
||
|
|
||
|
printk("Part number count: %d\n", part_number_count);
|
||
|
|
||
|
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
|