blob: 71c32218a2f22db96ed53dbaec52e69ebc5283c0 (
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
#lang racket
(require "../../lib/utils.rkt")
(require "../../lib/obj.rkt")
(define (read-input)
(call-with-input-file "input"
(λ (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 (collect-adjacent-positions num)
(define (position-range line start end)
(define delta (- end start))
(map list (repeat delta line) (range start end)))
(define left
(if (= 0 (num 'col))
'()
(list (list (num 'line) (- (num 'col) 1)))))
(define right
(if (= width (+ (num 'col) (num 'length)))
'()
(list (list (num 'line) (+ (num 'col) (num 'length))))))
(define up
(if (= 0 (num 'line))
'()
(position-range (- (num 'line) 1)
(max 0 (- (num 'col) 1))
(min width (+ (num 'col) (num 'length) 1)))))
(define down
(if (= (- height 1) (num 'line))
'()
(position-range (+ (num 'line) 1)
(max 0 (- (num 'col) 1))
(min width (+ (num 'col) (num 'length) 1)))))
(append left right up down))
(define asterisks (make-hash))
(define (mark-adj-asterisk num)
(define adjs (collect-adjacent-positions num))
(define (mark coord)
(if (not (char=? #\* (char-at (car coord) (cadr coord))))
(void)
(let ()
(when (not (hash-has-key? asterisks coord))
(hash-set! asterisks coord '()))
(hash-set! asterisks coord (cons (num 'value) (hash-ref asterisks coord))))))
(for-each mark adjs))
(for-each mark-adj-asterisk nums)
(define aster-list (hash->list asterisks))
(define (is-gear? aster)
(define nums-list (cdr aster))
(= 2 (length nums-list)))
(define (power aster)
(define nums-list (cdr aster))
(* (car nums-list) (cadr nums-list)))
(apply + (map power (filter is-gear? aster-list)))
|