diff options
Diffstat (limited to '3.scm')
-rwxr-xr-x | 3.scm | 61 |
1 files changed, 61 insertions, 0 deletions
@@ -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)))))) |