aboutsummaryrefslogtreecommitdiff
path: root/advent-of-code/2023/03
diff options
context:
space:
mode:
Diffstat (limited to 'advent-of-code/2023/03')
-rw-r--r--advent-of-code/2023/03/1.rkt84
-rw-r--r--advent-of-code/2023/03/2.rkt106
-rw-r--r--advent-of-code/2023/03/Makefile14
-rw-r--r--advent-of-code/2023/03/part1.c130
-rw-r--r--advent-of-code/2023/03/part2.c149
5 files changed, 190 insertions, 293 deletions
diff --git a/advent-of-code/2023/03/1.rkt b/advent-of-code/2023/03/1.rkt
new file mode 100644
index 0000000..537d65f
--- /dev/null
+++ b/advent-of-code/2023/03/1.rkt
@@ -0,0 +1,84 @@
+#lang racket/base
+
+(require "../lib/utils.rkt")
+(require "../lib/obj.rkt")
+
+(define (read-input)
+ (call-with-input-file "input"
+ (lambda (fp)
+ (list->vector (get-lines fp)))))
+
+(define schema (read-input))
+
+(define (char-at line col)
+ (string-ref (vector-ref schema line) col))
+
+(define height (vector-length schema))
+(define width (string-length (vector-ref schema 0)))
+
+(define make-num (obj-maker 'line 'col 'value 'length))
+
+(define (scan-nums)
+ (define nums '())
+ (let loop ((i 0))
+ (if (>= i height)
+ (void)
+ (let ()
+ (let loop ((j 0))
+ (define curline (vector-ref schema i))
+ (if (>= j width)
+ (void)
+ (let ()
+ (define next 1)
+ (define (find-next)
+ (if (or (>= (+ j next) 140)
+ (not (char-numeric? (char-at i (+ j next)))))
+ (void)
+ (let ()
+ (set! next (+ 1 next))
+ (find-next))))
+ (if (char-numeric? (char-at i j))
+ (let ()
+ (find-next)
+ (define value (string->number (substring curline j (+ j next))))
+ (set! nums (cons (make-num i j value next) nums)))
+ (void))
+ (loop (+ j next)))))
+ (loop (+ 1 i)))))
+ (reverse nums))
+(define nums (scan-nums))
+
+(define (is-symbol? c)
+ (and (not (char-numeric? c))
+ (not (char=? #\. c))))
+
+(define (collect-adjacent num)
+ (define left
+ (if (= 0 (num 'col))
+ '()
+ (list (char-at (num 'line) (- (num 'col) 1)))))
+ (define right
+ (if (= width (+ (num 'col) (num 'length)))
+ '()
+ (list (char-at (num 'line) (+ (num 'col) (num 'length))))))
+ (define up
+ (if (= 0 (num 'line))
+ '()
+ (string->list
+ (substring (vector-ref schema (- (num 'line) 1))
+ (max 0 (- (num 'col) 1))
+ (min width (+ (num 'col) (num 'length) 1))))))
+ (define down
+ (if (= (- height 1) (num 'line))
+ '()
+ (string->list
+ (substring (vector-ref schema (+ (num 'line) 1))
+ (max 0 (- (num 'col) 1))
+ (min width (+ (num 'col) (num 'length) 1))))))
+ (append left right up down))
+
+(define (is-part-num? num)
+ (findf is-symbol? (collect-adjacent num)))
+
+(apply + (map (lambda (x) (x 'value))
+ (filter is-part-num? nums))) \ No newline at end of file
diff --git a/advent-of-code/2023/03/2.rkt b/advent-of-code/2023/03/2.rkt
new file mode 100644
index 0000000..721a9d1
--- /dev/null
+++ b/advent-of-code/2023/03/2.rkt
@@ -0,0 +1,106 @@
+#lang racket
+
+(require "../lib/utils.rkt")
+(require "../lib/obj.rkt")
+
+(define (read-input)
+ (call-with-input-file "input"
+ (lambda (fp)
+ (list->vector (get-lines fp)))))
+
+(define schema (read-input))
+
+(define (char-at line col)
+ (string-ref (vector-ref schema line) col))
+
+(define height (vector-length schema))
+(define width (string-length (vector-ref schema 0)))
+
+(define make-num (obj-maker 'line 'col 'value 'length))
+
+(define (scan-nums)
+ (define nums '())
+ (let loop ((i 0))
+ (if (>= i height)
+ (void)
+ (let ()
+ (let loop ((j 0))
+ (define curline (vector-ref schema i))
+ (if (>= j width)
+ (void)
+ (let ()
+ (define next 1)
+ (define (find-next)
+ (if (or (>= (+ j next) 140)
+ (not (char-numeric? (char-at i (+ j next)))))
+ (void)
+ (let ()
+ (set! next (+ 1 next))
+ (find-next))))
+ (if (char-numeric? (char-at i j))
+ (let ()
+ (find-next)
+ (define value (string->number (substring curline j (+ j next))))
+ (set! nums (cons (make-num i j value next) nums)))
+ (void))
+ (loop (+ j next)))))
+ (loop (+ 1 i)))))
+ (reverse nums))
+(define nums (scan-nums))
+
+(define (is-symbol? c)
+ (and (not (char-numeric? c))
+ (not (char=? #\. c))))
+
+(define (collect-adjacent-positions num)
+ (define (position-range line start end)
+ (define delta (- end start))
+ (map list (repeat delta line) (range start end)))
+ (define left
+ (if (= 0 (num 'col))
+ '()
+ (list (list (num 'line) (- (num 'col) 1)))))
+ (define right
+ (if (= width (+ (num 'col) (num 'length)))
+ '()
+ (list (list (num 'line) (+ (num 'col) (num 'length))))))
+ (define up
+ (if (= 0 (num 'line))
+ '()
+ (position-range (- (num 'line) 1)
+ (max 0 (- (num 'col) 1))
+ (min width (+ (num 'col) (num 'length) 1)))))
+ (define down
+ (if (= (- height 1) (num 'line))
+ '()
+ (position-range (+ (num 'line) 1)
+ (max 0 (- (num 'col) 1))
+ (min width (+ (num 'col) (num 'length) 1)))))
+ (append left right up down))
+
+(define asterisks (make-hash))
+
+(define (mark-adj-asterisk num)
+ (define adjs (collect-adjacent-positions num))
+ (define (mark coord)
+ (if (not (char=? #\* (char-at (car coord) (cadr coord))))
+ (void)
+ (let ()
+ (when (not (hash-has-key? asterisks coord))
+ (hash-set! asterisks coord '()))
+ (hash-set! asterisks coord (cons (num 'value) (hash-ref asterisks coord))))))
+ (for-each mark adjs))
+
+(for-each mark-adj-asterisk nums)
+
+(define aster-list (hash->list asterisks))
+
+(define (is-gear? aster)
+ (define nums-list (cdr aster))
+ (= 2 (length nums-list)))
+
+(define (power aster)
+ (define nums-list (cdr aster))
+ (* (car nums-list) (cadr nums-list)))
+
+(apply + (map power (filter is-gear? aster-list)))
diff --git a/advent-of-code/2023/03/Makefile b/advent-of-code/2023/03/Makefile
deleted file mode 100644
index 44480b6..0000000
--- a/advent-of-code/2023/03/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-all: run
-
-run: part1 part2
- ./part1
- ./part2
-
-part1: part1.c
- gcc -g -I../lib/ ../lib/*.c part1.c -o part1
-
-part2: part2.c
- gcc -g -I../lib/ ../lib/*.c part2.c -o part2
-
-clean:
- rm part1 part2
diff --git a/advent-of-code/2023/03/part1.c b/advent-of-code/2023/03/part1.c
deleted file mode 100644
index 4ae9ef9..0000000
--- a/advent-of-code/2023/03/part1.c
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "vec.h"
-#include "str.h"
-
-void* read_input() {
- FILE* fp = fopen("./input", "r");
- void *vec = new_vec();
- while(1) {
- char *line = fgetline(fp);
- if (line == NULL) break;
- char *stripped = str_strip(line);
- if (strlen(stripped) == 0) break;
- vec_push_back(vec, stripped);
- }
- return vec;
-}
-
-typedef struct {
- int line;
- int column;
- int value;
- int length;
-} num_t;
-
-void *parse_nums(void *schema) {
- void *nums = new_vec();
- int j = 0;
- const int IN_NUM = 0, IDLE = 1;
- int state = IDLE;
- for (int i = 0; i < vec_size(schema); i++) {
- char *line = vec_get(schema, i);
- int line_len = strlen(line);
- int value = 0;
- int length = 0;
- state = IDLE;
- j = 0;
- while (1) {
- char c = '.';
- if (j < line_len) c = line[j];
- if (state == IDLE) {
- if (isdigit(c)) {
- state = IN_NUM;
- continue;
- } else {
- j++;
- if (j >= line_len) break;
- continue;
- }
- } else if (state == IN_NUM) {
- if (isdigit(c)) {
- value = value * 10 + (c - '0');
- length++;
- j++;
- continue;
- } else {
- num_t *n = malloc(sizeof(num_t));
- *n = (num_t){
- .line = i,
- .column = j - length,
- .value = value,
- .length = length
- };
- vec_push_back(nums, n);
- value = 0;
- length = 0;
- state = IDLE;
- if (j >= line_len) break;
- continue;
- }
- }
- }
- }
- return nums;
-}
-
-int is_symbol(char c) {
- if (c >= '0' && c <= '9') return 0;
- if (c == '.') return 0;
- return 1;
-}
-
-int is_a_part(void *schema, num_t *num) {
- int line_len = vec_size(schema);
- int col_len = strlen(vec_get(schema, 0));
- for (int i = num->column - 1; i < num->column + num->length + 1; i++) {
- if (num->line - 1 < 0) continue;
- if (i < 0 || i >= col_len) continue;
- if (is_symbol(((char*)vec_get(schema, num->line - 1))[i])) {
- return 1;
- }
- }
- for (int i = num->column - 1; i < num->column + num->length + 1; i++) {
- if (num->line + 1 >= line_len) continue;
- if (i < 0 || i >= col_len) continue;
- if (is_symbol(((char*)vec_get(schema, num->line + 1))[i])) {
- return 1;
- }
- }
- if (num->column - 1 >= 0) {
- if (is_symbol(((char*)vec_get(schema, num->line))[num->column - 1])) {
- return 1;
- }
- }
- if (num->column + num->length < col_len) {
- char *line = vec_get(schema, num->line);
- if (is_symbol(line[num->column + num->length])) {
- return 1;
- }
- }
- return 0;
-}
-
-int main() {
- void *schema = read_input();
- void *nums = parse_nums(schema);
- int sum = 0;
- for (int i = 0; i < vec_size(nums); i++) {
- num_t *num = vec_get(nums, i);
- if (is_a_part(schema, num)) {
- sum += num->value;
- }
- }
- printf("%d\n", sum);
- return 0;
-}
diff --git a/advent-of-code/2023/03/part2.c b/advent-of-code/2023/03/part2.c
deleted file mode 100644
index a5ab825..0000000
--- a/advent-of-code/2023/03/part2.c
+++ /dev/null
@@ -1,149 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "vec.h"
-#include "str.h"
-#include "map.h"
-
-void* read_input() {
- FILE* fp = fopen("./input", "r");
- void *vec = new_vec();
- while(1) {
- char *line = fgetline(fp);
- if (line == NULL) break;
- char *stripped = str_strip(line);
- if (strlen(stripped) == 0) break;
- vec_push_back(vec, stripped);
- }
- return vec;
-}
-
-typedef struct {
- int line;
- int column;
- int value;
- int length;
-} num_t;
-
-char *compose_key(int x, int y) {
- void* ss = new_ss();
- ss_add(ss, "%d,%d", x, y);
- return ss_cstr(ss);
-}
-
-void *parse_nums(void *schema) {
- void *nums = new_vec();
- int j = 0;
- const int IN_NUM = 0, IDLE = 1;
- int state = IDLE;
- for (int i = 0; i < vec_size(schema); i++) {
- char *line = vec_get(schema, i);
- int line_len = strlen(line);
- int value = 0;
- int length = 0;
- state = IDLE;
- j = 0;
- while (1) {
- char c = '.';
- if (j < line_len) c = line[j];
- if (state == IDLE) {
- if (isdigit(c)) {
- state = IN_NUM;
- continue;
- } else {
- j++;
- if (j >= line_len) break;
- continue;
- }
- } else if (state == IN_NUM) {
- if (isdigit(c)) {
- value = value * 10 + (c - '0');
- length++;
- j++;
- continue;
- } else {
- num_t *n = malloc(sizeof(num_t));
- *n = (num_t){
- .line = i,
- .column = j - length,
- .value = value,
- .length = length
- };
- vec_push_back(nums, n);
- value = 0;
- length = 0;
- state = IDLE;
- if (j >= line_len) break;
- continue;
- }
- }
- }
- }
- return nums;
-}
-
-char char_at(void *schema, int line, int column) {
- char *buf = vec_get(schema, line);
- return buf[column];
-}
-
-void mark_asterisks(void *asterisks, num_t *num, int x, int y) {
- const char *key = compose_key(x, y);
- void *num_list = dict_get(asterisks, key);
- if (num_list == NULL) {
- num_list = new_vec();
- dict_set(asterisks, key, num_list);
- }
- vec_push_back(num_list, num);
-}
-
-void find_asterisks(void *schema, void *asterisks, num_t *num) {
- int line_len = vec_size(schema);
- int col_len = strlen(vec_get(schema, 0));
- for (int i = num->column - 1; i < num->column + num->length + 1; i++) {
- if (num->line - 1 < 0) continue;
- if (i < 0 || i >= col_len) continue;
- char c = char_at(schema, num->line - 1, i);
- if (c == '*') mark_asterisks(asterisks, num, num->line - 1, i);
- }
- for (int i = num->column - 1; i < num->column + num->length + 1; i++) {
- if (num->line + 1 >= line_len) continue;
- if (i < 0 || i >= col_len) continue;
- char c = char_at(schema, num->line + 1, i);
- if (c == '*') mark_asterisks(asterisks, num, num->line + 1, i);
- }
- if (num->column - 1 >= 0) {
- char c = char_at(schema, num->line, num->column - 1);
- if (c == '*') mark_asterisks(asterisks, num, num->line, num->column - 1);
- }
- if (num->column + num->length < col_len) {
- char c = char_at(schema, num->line, num->column + num->length);
- if (c == '*') mark_asterisks(asterisks, num, num->line, num->column + num->length);
- }
-}
-
-int main() {
- void *schema = read_input();
- void *nums = parse_nums(schema);
- int sum = 0;
- void *asterisks = new_dict();
- for (int i = 0; i < vec_size(nums); i++) {
- num_t *num = vec_get(nums, i);
- find_asterisks(schema, asterisks, num);
- }
- for (void *iter = dict_begin(asterisks);
- iter != NULL;
- iter = dict_next(asterisks, iter)) {
- void *list = dict_iter_value(iter);
- if (vec_size(list) == 2) {
- num_t* n1 = vec_get(list, 0);
- num_t* n2 = vec_get(list, 1);
- sum += n1->value * n2->value;
- }
- }
- printf("%d\n", sum);
- return 0;
-}