From 2e904e83f6fbc001e5b265d94283841a51050fac Mon Sep 17 00:00:00 2001 From: Juan MarĂ­n Noguera Date: Sun, 15 Dec 2024 11:59:53 +0100 Subject: Days 08--12 These days have been done while traveling, so they may be less modular due to time/phone-screen constraints. --- day08.scm | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 day08.scm (limited to 'day08.scm') diff --git a/day08.scm b/day08.scm new file mode 100644 index 0000000..a697de8 --- /dev/null +++ b/day08.scm @@ -0,0 +1,122 @@ +(define-module (day08) + #:use-module (ice-9 rdelim) + #:use-module (oop goops) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) + #:use-module (srfi srfi-43)) + +(define-class () + #| A description of the problem at hand. |# + (height #:init-value 0 #:accessor problem-height #| The height of the map. |#) + (width #:init-value 0 #:accessor problem-width #| The width of the map. |#) + (nodes #:init-thunk make-hash-table + #| A hashv that associates each letter that appears with a list of + positions of antennas, represented as (y, x) pairs. |#)) + +(define-method (display (problem ) port) + (define result + (list->vector + (list-tabulate (problem-height problem) + (lambda (_i) (make-string (problem-width problem) #\.))))) + (define (add-dots c pts) + (unless (null? pts) + (when (and (< -1 (caar pts) (problem-height problem)) + (< -1 (cdar pts) (problem-width problem))) + (string-set! (vector-ref result (caar pts)) (cdar pts) c)))) + (hash-for-each add-dots result) + (vector-for-each (cut write-line <> port) result)) + +(define (problem-add! problem y x chr) + (define ht (slot-ref problem 'nodes)) + (hashv-set! ht chr + (cons (cons y x) (hashv-ref ht chr '())))) + +(define (problem-nodes problem chr) + (hashv-ref (slot-ref problem 'nodes) chr '())) + +(define* (read-problem #:optional (port (current-input-port))) + (define problem (make )) + (define (iter y w) + (define line (read-line)) + (if (or (eof-object? line) (string= line "")) + (begin (set! (problem-width problem) w) + (set! (problem-height problem) y)) + (begin + (string-for-each-index + (lambda (i) + (unless (char=? (string-ref line i) #\.) + (problem-add! problem y i (string-ref line i)))) + line) + (iter (+ y 1) (max w (string-length line)))))) + (iter 0 0) + problem) + +(define (antinode n1 n2) + (cons (- (* 2 (car n2)) (car n1)) + (- (* 2 (cdr n2)) (cdr n1)))) + +(define (add-point! mp pt) + (when (array-in-bounds? mp (car pt) (cdr pt)) + (array-set! mp 1 (car pt) (cdr pt)))) + +(define (problem-count-anti-nodes problem) + (define mp (make-array 0 (problem-height problem) + (problem-width problem))) + (define count 0) + (define (add-from poss) + (unless (null-list? poss) + (for-each + (lambda (t) + (add-point! mp (antinode (car poss) t)) + (add-point! mp (antinode t (car poss)))) + (cdr poss)) + (add-from (cdr poss)))) + (hash-for-each (lambda (chr poss) (add-from poss)) + (slot-ref problem 'nodes)) + (array-for-each (lambda (x) (set! count (+ count x))) + mp) + count) + +(define* (part1 #:optional (port (current-input-port))) + (problem-count-anti-nodes (read-problem port))) + +(define (add-antinodes! mp n1 n2) + (define vy (- (car n2) (car n1))) + (define vx (- (cdr n2) (cdr n1))) + (define divider (gcd vx vy)) + (define dy (/ vy divider)) + (define dx (/ vx divider)) + (define-values (h w) (apply values (array-dimensions mp))) + (define y1 (- (/ (car n1) dy))) + (define y2 (/ (- h 1 (car n1)) dy)) + (define x1 (- (/ (cdr n1) dx))) + (define x2 (/ (- w 1 (cdr n1)) dx)) + (define kstart (ceiling (max (min x1 x2) (min y1 y2)))) + (define kend (floor (min (max x1 x2) (max y1 y2)))) + (define (iter k) + (unless (> k kend) + (array-set! mp 1 (+ (car n1) (* k dy)) + (+ (cdr n1) (* k dx))) + (iter (+ k 1)))) + (iter kstart)) + +(define (problem-count-anti-nodes2 problem) + (define mp (make-array 0 (problem-height problem) + (problem-width problem))) + (define count 0) + (define (add-from poss) + (unless (null-list? poss) + (for-each + (lambda (t) + (add-antinodes! mp (car poss) t)) + (cdr poss)) + (add-from (cdr poss)))) + (hash-for-each (lambda (chr poss) (add-from poss)) + (slot-ref problem 'nodes)) + (array-for-each (lambda (x) (set! count (+ count x))) + mp) + count) + +(define* (part2 #:optional (port (current-input-port))) + (problem-count-anti-nodes2 (read-problem port))) + -- cgit v1.2.3