aboutsummaryrefslogtreecommitdiff
path: root/day03.scm
blob: 983d8b59818f9fdb3d34007d69abe85f6a69c8b9 (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
(define-module (day03)
  #:use-module (srfi srfi-41)
  #:use-module (ice-9 match)
  #:use-module (ice-9 rdelim)
  #:use-module (ice-9 regex)
  #:export (part1 part2))

(define mul-regexp (make-regexp "mul\\(([0-9]+),([0-9]+)\\)|do\\(\\)|(don't\\(\\))"))

(define (parse-instruction match)
  (cond ((match:start match 3) 'dont)
        ((match:start match 1) (list 'mul
                                     (string->number (match:substring match 1))
                                     (string->number (match:substring match 2))))
        (else 'do)))

(define* (input-instructions #:optional (port (current-input-port)))
  (stream-let loop ((line (read-line port)) (start 0))
              (if (eof-object? line)
                  stream-null
                  (let ((mch (regexp-exec mul-regexp line start)))
                    (if mch
                        (stream-cons (parse-instruction mch)
                                     (loop line (match:end mch)))
                        (loop (read-line port) 0))))))

(define (mul-op? x)
  (and (pair? x) (eq? 'mul (car x))))

(define* (part1 #:optional (port (current-input-port)))
  (stream-fold + 0
               (stream-map (lambda (op) (apply * (cdr op)))
                           (stream-filter mul-op? (input-instructions port)))))

(define* (part2 #:optional (port (current-input-port)))
  (let ((sum 0) (on? #t))
    (stream-for-each
     (match-lambda
       ('do (set! on? #t))
       ('dont (set! on? #f))
       (('mul x y) (when on? (set! sum (+ sum (* x y))))))
     (input-instructions port))
    sum))