summaryrefslogtreecommitdiff
path: root/3-2.scm
blob: d20f63c812dd9c3ccf9ec240760335642723b381 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/bin/env -S guile -s
!#
(use-modules (ice-9 regex)
             (ice-9 textual-ports)
             (srfi srfi-1))

(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 (matches-for-line line regex)
  (letrec ((loop (lambda (l ls)
                   (if (not l) ls
                        (loop (string-match regex line (match:end l)) (cons l ls))))))
    (loop (string-match regex line) '())))

(define (find-candidates lines)
  (let ((i -1))
    (concatenate (map-in-order (lambda (line) (let ((cands (matches-for-line line "[0-9]+")))
                                   (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 (find-gears lines)
    (let ((i -1))
    (concatenate (map-in-order (lambda (line) (let ((cands (matches-for-line line "\\*")))
                                   (set! i (+ i 1))
                                   (map (lambda (cand)
                                          `(,i ,(match:start cand))) cands))) lines))))

(define (parts-for-gear parts gear)
  (filter (lambda (part)
            (and (>= (car part) (- (car gear) 1))
                 (<= (car part) (+ (car gear) 1))
                 (<= (- (cadr gear) (cadr part)) (caddr part))
                 (>= (- (cadr gear) (cadr part)) -1))) parts))

(let* ((port (open-input-file "3.txt"))
       (lines (read-lines port))
       (parts (find-candidates lines)))
  (close-port port)
  (display (fold + 0 (map (lambda (x) (* (car x) (cadr x))) (filter (lambda (x) (= (length x) 2)) (map (lambda (gear) (map cadddr (parts-for-gear parts gear))) (find-gears lines)))))))