#include #include #include #include #define MODULE_NAME "aoc2023d3p2" MODULE_AUTHOR("logan2611"); MODULE_LICENSE("Dual MIT/GPL"); MODULE_DESCRIPTION("Advent of Code 2023 Day 3 Part 2 (The Linux Kernel Module)"); MODULE_VERSION("0.1"); const int length = 140; // Number of lines //const int length = 10; // Number of lines const int width = length + 1; // Width of lines (including newline, carriage return or null terminator) // Parameter that specifies the input file static char *path = "/tmp/input"; module_param(path, charp, S_IRUGO); MODULE_PARM_DESC(path, "The path to the data input."); static ssize_t read_input(struct file *file, loff_t pos, size_t n, char *buffer) { ssize_t bytes_read; bytes_read = kernel_read(file, buffer, n, &pos); if (bytes_read < 0) { pr_err("%s: Error reading file: %zd\n", MODULE_NAME, bytes_read); } return bytes_read; } static void make_num_string(char *input, char *output, int head, int tail) { memcpy(output, input + head, tail+1-head); } static int atoi(char *input) { int ret; int err = kstrtoint(input, 10, &ret); if (err < 0) { //pr_err("%s: Failed to convert string to number: \"%d\"\n", MODULE_NAME, err); return 0; } return ret; } static int find_head_number(char *input, int pos) { while(isdigit(input[pos]) && pos >= 0) { //pr_info("%s: Scanning head: %c (%d)\n", MODULE_NAME, input[pos], pos); pos--; } //pr_info("%s: Found head: %c (%d)\n", MODULE_NAME, input[pos], pos); return pos + 1; } static int find_tail_number(char *input, int head) { while(isdigit(input[head])) { //pr_info("%s: Scanning tail: %c (%d)\n", MODULE_NAME, input[head], head); head++; } //pr_info("%s: Found tail: %c (%d)\n", MODULE_NAME, input[head], head); return head - 1; } static int find_adjacent_numbers(char *top, char *middle, char *bottom, int offset) { int adjacent = 0; int prod = 1; int topskip = 0; int midskip = 0; int botskip = 0; for(int pos = offset-1; pos <= offset+1; pos++) { //pr_info("%s: Scanning position %d\n", MODULE_NAME, pos); if(isdigit(top[pos]) && pos > topskip) { int head = find_head_number(top, pos); int tail = find_tail_number(top, head); char numstr[8] = {0}; make_num_string(top, numstr, head, tail); prod *= atoi(numstr); adjacent++; topskip = tail; pr_info("%s: Found adjacent number top: %d %d-%d v:%d\n", MODULE_NAME, pos, head, tail, atoi(numstr)); } if(isdigit(middle[pos]) && pos > midskip) { int head = find_head_number(middle, pos); int tail = find_tail_number(middle, head); char numstr[8] = {0}; make_num_string(middle, numstr, head, tail); prod *= atoi(numstr); adjacent++; midskip = tail; pr_info("%s: Found adjacent number mid: %d %d-%d v:%d\n", MODULE_NAME, pos, head, tail, atoi(numstr)); } if(isdigit(bottom[pos]) && pos > botskip) { int head = find_head_number(bottom, pos); int tail = find_tail_number(bottom, head); char numstr[8] = {0}; make_num_string(bottom, numstr, head, tail); prod *= atoi(numstr); adjacent++; botskip = tail; pr_info("%s: Found adjacent number bottom: %d %d-%d v:%d\n", MODULE_NAME, pos, head, tail, atoi(numstr)); } } if(adjacent == 2) { return prod; } else { return 0; } } static int find_stars(char *top, char *middle, char *bottom) { int beginning = -1; int sum = 0; for(int i = 0; i < width; i++) { if(middle[i] == '*') { beginning = i; pr_info("%s: Found star: %d\n", MODULE_NAME, i); sum += find_adjacent_numbers(top, middle, bottom, beginning); } } return sum; } static int __init test_init(void) { struct file *f; pr_info("%s: Module loaded\n", MODULE_NAME); f = filp_open(path, O_RDONLY, 0); if(IS_ERR(f)) { pr_err("%s: Failed to open %s\n", MODULE_NAME, path); return PTR_ERR(f); } char buf[3][width+1]; memset(buf, 0, sizeof(buf)); read_input(f, 0, width, buf[2]); int sum = 0; for(int line = 1; line <= length; line++) { pr_info("%s: %s", MODULE_NAME, buf[2]); memcpy(buf[0], buf[1], sizeof(buf[0])); memcpy(buf[1], buf[2], sizeof(buf[1])); if(length - line > 0) { read_input(f, line*width, length, buf[2]); } else { memset(buf[2], 0, sizeof(buf[2])); } sum += find_stars(buf[0], buf[1], buf[2]); } filp_close(f, NULL); pr_info("%s: Answer: %d\n", MODULE_NAME, sum); return 0; } static void __exit test_exit(void) { pr_info("%s: Module unloaded\n", MODULE_NAME); } module_init(test_init); module_exit(test_exit);