aboutsummaryrefslogtreecommitdiff
path: root/day25.scm
blob: 57cdb9d574e3497947f1ec0f2b3cc4f4f5138b04 (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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
(define-module (day25)
  #:use-module (ice-9 rdelim)
  #:use-module (rnrs io ports)
  #:use-module (srfi srfi-1)
  #:use-module (srfi srfi-43))

(define +block-chars+ (char-set #\# #\.))

(define (read-key-or-lock port topc expect-end)
  (define vec (make-vector 5 0))
  (let iter ((i 0))
    (unless (= i 5)
      (let ((line (read-line port)))
        (when (eof-object? line)
          (error "Unexpected EOF in the middle of a key."))
        (unless (string-every +block-chars+ line)
          (error "Lines in keys/locks must be '#' or '.'." line))
        (let jiter ((j 0))
          (unless (= j 5)
            (when (char=? topc (string-ref line j))
              (unless (= i (vector-ref vec j))
                (error
                 (string-append "Columns must be all '#' followed by all '.' "
                                "or vice versa; cannot alternate.")
                 vec line i j))
              (vector-set! vec j (+ i 1)))
            (jiter (+ j 1)))))
      (iter (+ i 1))))
  (define end-line (read-line port))
  (unless (equal? end-line expect-end)
    (error "Expected key/lock end line to be ~a; got ~a." expect-end end-line))
  (define blank (read-line port))
  (unless (or (eof-object? blank) (string=? "" blank))
    (error "Expected blank line or end-of-file." blank))
  vec)

(define (read-key port)
  (define line (read-line port))
  (cond ((or (eof-object? line) (string=? "" line))
         (values (eof-object) (eof-object)))
        ((string=? line ".....")
         (values 'key (read-key-or-lock port #\. "#####")))
        ((string=? line "#####")
         (values 'lock (read-key-or-lock port #\# ".....")))
        (else (error "Expected key ('.....') or lock ('#####')." line))))

(define (read-input port)
  (let iter ((keys '()) (locks '()))
    (define-values (type vec) (read-key port))
    (cond ((eof-object? type) (values keys locks))
          ((eq? type 'key) (iter (cons vec keys) locks))
          (else (iter keys (cons vec locks))))))

(define (part1 port)
  (define-values (keys locks) (read-input port))
  (fold (lambda (key cnt)
          (fold (lambda (lock cnt)
                  (if (vector-every >= key lock) (+ cnt 1) cnt)) cnt locks))
        0 keys))

(define (part2 port)
  "yay!")