🎄⌨️ Advent of Code 2018

Check-in [93400b]
Overview
Comment:Add Day 11 solutions
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 93400b694c7d79c6bd4a88bfb158f2e6b81d06bc90724214bbd44dcac49591f9
User & Date: joel on 2018-12-17 02:04:52
Other Links: manifest | tags
Context
2018-12-18
01:39
Add Day 12 input and examples check-in: f3ec8e user: joel tags: trunk
2018-12-17
02:04
Add Day 11 solutions check-in: 93400b user: joel tags: trunk
2018-12-15
22:30
Add Day 10 solutions and output check-in: c54f37 user: joel tags: trunk
Changes

Added day11.rkt version [221e1a].



















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
103
104
105
#lang racket

(require rackunit sugar/debug)

;; Since the input is just a single number, we’ll make it a parameter.
(define input (make-parameter 9424)) ; = my input
(define square-size (make-parameter 3))

;; Return the hundreds digit of a number if there is one, or zero if there isn’t
(define (hundreds-digit n)
  (cond [(< n 100) 0]
        [else (let* ([str (number->string n)]
                     [strlen (string-length str)]
                     [start (- strlen 3)])
                (string->number (substring str start (+ 1 start))))]))

;; Calculates the power at the given coordinates
(define (power-at x y)
  (let* ([rack-id (+ x 10)]
         [powerlevel (+ (input) (* rack-id y))]
         [powerlevel (* powerlevel rack-id)]
         [powerlevel (hundreds-digit powerlevel)])
    (- powerlevel 5)))

;; Make sure we’re getting values that match the examples
(module+ test
  (parameterize ([input 8])
    (check-equal? (power-at 3 5) 4))
  (parameterize ([input 57])
    (check-equal? (power-at 122 79) -5))
  (parameterize ([input 39])
    (check-equal? (power-at 217 196) 0))
  (parameterize ([input 71])
    (check-equal? (power-at 101 153) 4)))

;; I have a notion that numeric keys for hash tables are faster somehow
(define (grid-key x y)
  (+ (* 1000 x) y))

;; If either coord is zero, returns 0
(define (ref-z h x y)
  (cond [(zero? (* x y)) 0]
        [else (hash-ref h (grid-key x y))]))
         
;; Returns a summed-area hash table
(define (summed-area-grid)
  (for*/fold ([table (hash)])
             ([x (in-range 1 301)]
              [y (in-range 1 301)])
    (define cur (- (+ (power-at x y)
                      (ref-z table x (sub1 y))
                      (ref-z table (sub1 x) y))
                   (ref-z table (sub1 x) (sub1 y))))
    (hash-set table (grid-key x y) cur)))

;; Return the total power-level of the square of the grid starting at x,y
(define (square-total-power grid x y)
  (- (+ (ref-z grid (sub1 x) (sub1 y))
        (hash-ref grid (grid-key (+ x (sub1 (square-size)))
                                 (+ y (sub1 (square-size))))))
     (ref-z grid (sub1 x) (+ y (sub1 (square-size))))
     (ref-z grid (+ x (sub1 (square-size))) (sub1 y))))

;; Check the sums against the examples
(module+ test
  (parameterize ([input 18])
    (check-equal? (square-total-power (summed-area-grid) 33 45) 29))
  (parameterize ([input 42])
    (check-equal? (square-total-power (summed-area-grid) 21 61) 30)))

;; Returns a list of the power levels for all the NxN squares in the grid
;; Each item in the list identifies the power level, coords, and square size
(define (square-power-levels grid)
  (define end-before (- 300 (max 0 (- (square-size) 2))))
  (for*/list ([x (in-range 1 end-before)]
              [y (in-range 1 end-before)])
             (list (square-total-power grid x y) x y (square-size))))

;; Return the power-levl and coordinates of the upper left cell in the
;; 3x3 quadrant with the highest total power
(define (day11-part1 grid)
  (first (sort (square-power-levels grid) > #:key car)))

;; Test with examples, then for real
(module+ test
  (parameterize ([input 18])
    (check-equal? (day11-part1 (summed-area-grid)) '(29 33 45 3)))
  (parameterize ([input 42])
    (check-equal? (day11-part1 (summed-area-grid)) '(30 21 61 3)))
  
  (check-equal? (report (time (day11-part1 (summed-area-grid))))
                '(28 243 72 3))) ; 243,72 = correct answer for part 1

;; Test all square sizes from 1 to 300, find the coordinates and size of
;; the square with the highest total power
(define (day11-part2)
  (define grid (summed-area-grid))
  (define candidates
    (for/list ([i (in-range 1 301)])
              (parameterize ([square-size i])
                (day11-part1 grid))))
  (first (sort candidates > #:key car)))

(module+ test
  (check-equal? (report (time (day11-part2))) '(74 229 192 11))) ; 229,192,11 = correct answer for part 2