summaryrefslogtreecommitdiff
path: root/3.scm
diff options
context:
space:
mode:
authorlamp2023-12-04 01:28:22 +0000
committerlamp2023-12-04 01:28:22 +0000
commit8714ae3ac6eb5c77fdf5103685a926e3b482612b (patch)
tree4cdc2ddfb220f1b2ef4e7c4938ea4eda7aafd37b /3.scm
parent78232b574dc4eba001d536a865c115582c4e2325 (diff)
add day 3 solutions
Diffstat (limited to '3.scm')
-rwxr-xr-x3.scm61
1 files changed, 61 insertions, 0 deletions
diff --git a/3.scm b/3.scm
new file mode 100755
index 0000000..c43d0bd
--- /dev/null
+++ b/3.scm
@@ -0,0 +1,61 @@
+#!/usr/bin/env -S guile -s
+!#
+(use-modules (ice-9 regex)
+ (ice-9 textual-ports)
+ (srfi srfi-1))
+
+(define line-length 140) ;; nasty :(
+
+(define (read-lines port)
+ (letrec ((loop (lambda (l ls)
+ (if (eof-object? l)
+ ls
+ (loop (get-line port) (cons l ls))))))
+ (reverse (loop (get-line port) '()))))
+
+(define (candidates-for-line line)
+ (letrec ((loop (lambda (l ls)
+ (if (not l) ls
+ (loop (string-match "[0-9]+" line (match:end l)) (cons l ls))))))
+ (loop (string-match "[0-9]+" line) '())))
+
+(define (find-candidates lines)
+ (let ((i -1))
+ (concatenate (map-in-order (lambda (line) (let ((cands (candidates-for-line line)))
+ (set! i (+ i 1))
+ (map (lambda (cand)
+ `(,i ,(match:start cand) ,(- (match:end cand) (match:start cand)) ,(string->number (match:substring cand)))) cands))) lines))))
+
+(define (saturating-add lhs rhs max)
+ (let ((res (+ lhs rhs)))
+ (if (> res max) max res)))
+
+(define (saturating-sub lhs rhs min)
+ (let ((res (- lhs rhs)))
+ (if (< res min) min res)))
+
+(define (contains-part-symbol? str)
+ (string-match "[^0-9|\\.]" str))
+
+(define (part-number? candidate lines)
+ (let ((above (substring (list-ref lines (saturating-sub (car candidate) 1 0))
+ (saturating-sub (cadr candidate) 1 0)
+ (saturating-add (+ (cadr candidate) (caddr candidate)) 1 line-length)))
+ (below (substring (list-ref lines (saturating-add (car candidate) 1 (- (length lines) 1)))
+ (saturating-sub (cadr candidate) 1 0)
+ (saturating-add (+ (cadr candidate) (caddr candidate)) 1 line-length)))
+ (left (substring (list-ref lines (car candidate))
+ (saturating-sub (cadr candidate) 1 0)
+ (cadr candidate)))
+ (right (substring (list-ref lines (car candidate))
+ (+ (cadr candidate) (caddr candidate))
+ (saturating-add (+ (cadr candidate) (caddr candidate)) 1 line-length))))
+ (or (contains-part-symbol? above)
+ (contains-part-symbol? below)
+ (contains-part-symbol? left)
+ (contains-part-symbol? right))))
+
+(let* ((port (open-input-file "3.txt"))
+ (lines (read-lines port)))
+ (close-port port)
+ (display (fold + 0 (map cadddr (filter (lambda (cand) (part-number? cand lines)) (find-candidates lines))))))