aboutsummaryrefslogtreecommitdiff
path: root/advent-of-code/2023/03/1.rkt
blob: 09bc7d0a7b2bd22d818f1505d7e6f5042208f3f2 (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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#lang racket/base

(require "../../lib/utils.rkt")
(require "../../lib/obj.rkt")

(define (read-input)
  (call-with-input-file "input"
    (lambda (fp) 
      (list->vector (get-lines fp)))))

(define schema (read-input))

(define (char-at line col)
  (string-ref (vector-ref schema line) col))

(define height (vector-length schema))
(define width (string-length (vector-ref schema 0)))

(define make-num (obj-maker 'line 'col 'value 'length))

(define (scan-nums)
  (define nums '())
  (let loop ((i 0))
    (if (>= i height)
      (void)
      (let ()
        (let loop ((j 0))
            (define curline (vector-ref schema i))
            (if (>= j width)
            (void)
            (let ()
                (define next 1)
                (define (find-next)
                  (if (or (>= (+ j next) 140)
                          (not (char-numeric? (char-at i (+ j next)))))
                    (void)
                    (let ()
                      (set! next (+ 1 next))
                      (find-next))))
                (if (char-numeric? (char-at i j))
                  (let ()
                    (find-next)
                    (define value (string->number (substring curline j (+ j next))))
                    (set! nums (cons (make-num i j value next) nums)))
                  (void))
                (loop (+ j next)))))
        (loop (+ 1 i)))))
  (reverse nums))
(define nums (scan-nums))

(define (is-symbol? c)
  (and (not (char-numeric? c))
       (not (char=? #\. c))))

(define (collect-adjacent num)
  (define left
    (if (= 0 (num 'col))
      '()
      (list (char-at (num 'line) (- (num 'col) 1)))))
  (define right
    (if (= width (+ (num 'col) (num 'length)))
      '()
      (list (char-at (num 'line) (+ (num 'col) (num 'length))))))
  (define up
    (if (= 0 (num 'line))
      '()
      (string->list
        (substring (vector-ref schema (- (num 'line) 1))
                   (max 0 (- (num 'col) 1))
                   (min width (+ (num 'col) (num 'length) 1))))))
  (define down
    (if (= (- height 1) (num 'line))
      '()
      (string->list
        (substring (vector-ref schema (+ (num 'line) 1))
                   (max 0 (- (num 'col) 1))
                   (min width (+ (num 'col) (num 'length) 1))))))
  (append left right up down))

(define (is-part-num? num)
  (findf is-symbol? (collect-adjacent num)))

(apply + (map (lambda (x) (x 'value))
              (filter is-part-num? nums)))