Advertisement
dalmationblack

Day 9 Solution

Dec 9th, 2021
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 8.39 KB | None | 0 0
  1. ;; Language: Racket Intermediate Student with Lambda
  2.  
  3. (require 2htdp/batch-io)
  4.  
  5. ;; day 9 part 1
  6. ;; find low points of grid
  7.  
  8. ;; get-risk-level-sum : String -> Number
  9. ;; gets the sum of the risk levels from the lowest points
  10. ;; in the grid in the given file
  11.  
  12. (check-expect (get-risk-level-sum "advent-smoke-1.txt") 15)
  13.  
  14. (define (get-risk-level-sum filename)
  15.   (local [(define GRID (los->grid (read-lines filename)))]
  16.     (foldr
  17.      (λ (height sum) (+ 1 height sum))
  18.      0
  19.      (map
  20.       (λ (p) (find-num-at-coordinates GRID p))
  21.       (find-low-points GRID)))))
  22.  
  23. ;; los->grid : [List-of String] -> [List-of [List-of Number]]
  24. ;; converts the strings to a grid
  25.  
  26. (check-expect (los->grid (list "123" "456" "789"))
  27.               (list (list 1 2 3)
  28.                     (list 4 5 6)
  29.                     (list 7 8 9)))
  30. (check-expect (los->grid (list "36" "43"))
  31.               (list (list 3 6)
  32.                     (list 4 3)))
  33.  
  34. (define (los->grid los)
  35.   (map (λ (str) (map string->number (explode str))) los))
  36.  
  37. ;; find-low-points : [List-of [List-of Number]] -> [List-of Position]
  38. ;; find the low points in the grid
  39.  
  40. (check-expect (find-low-points (list (list 1 2 3)
  41.                                      (list 1 2 3)
  42.                                      (list 1 2 3)))
  43.               '())
  44. (check-expect (find-low-points (list (list 1 2 3)
  45.                                      (list 4 5 6)
  46.                                      (list 7 8 9)))
  47.               (list (make-posn 0 0)))
  48. (check-expect (find-low-points (list (list 1 2 3)
  49.                                      (list 4 5 6)
  50.                                      (list 7 8 5)))
  51.               (list (make-posn 0 0) (make-posn 2 2)))
  52.  
  53. (define (find-low-points grid)
  54.   (local [(define HEIGHT (length grid))
  55.           (define WIDTH (length (first grid)))
  56.          
  57.           ;; find-low-points/acc : Nat Nat -> [List-of Number]
  58.           ;; finds the low points in the grid
  59.           ;; Accumulator: the x and y coordinates of the current number
  60.           (define (find-low-points/acc x y)
  61.             (cond
  62.               [(= x WIDTH) (find-low-points/acc 0 (add1 y))]
  63.               [(= y HEIGHT) '()]
  64.               [else
  65.                (local [(define CURR (list-ref (list-ref grid y) x))
  66.                        (define PREV (find-low-points/acc (add1 x) y))
  67.                        (define POSN (make-posn x y))]
  68.                  (if (all-less-than? CURR (find-adjacent grid POSN))
  69.                      (cons POSN PREV)
  70.                      PREV))]))]
  71.     (find-low-points/acc 0 0)))
  72.  
  73. ;; all-less-than? : Number [List-of Number] -> Boolean
  74. ;; is the number lower than all numbers in the list?
  75.  
  76. (check-expect (all-less-than? 4 (list 5 6 7)) #true)
  77. (check-expect (all-less-than? 4 (list 1 6 7)) #false)
  78. (check-expect (all-less-than? 4 (list 4 6 7)) #false)
  79.  
  80. (define (all-less-than? num lon)
  81.   (andmap (λ (n) (< num n)) lon))
  82.  
  83. ;; find-adjacent : [List-of [List-of Number]] Position -> [List-of Number]
  84. ;; find the adjacent points to the current point
  85. ;; points off the grid are considered to be 9
  86.  
  87. (check-expect (find-adjacent (list (list 1 2 3)
  88.                                    (list 4 5 6)
  89.                                    (list 7 8 9))
  90.                              (make-posn 1 1))
  91.               (list 2 4 6 8))
  92. (check-expect (find-adjacent (list (list 1 2 3)
  93.                                    (list 4 5 6)
  94.                                    (list 7 8 9))
  95.                              (make-posn 1 0))
  96.               (list 9 1 3 5))
  97. (check-expect (find-adjacent (list (list 1 2 3)
  98.                                    (list 4 5 6)
  99.                                    (list 7 8 9))
  100.                              (make-posn 2 2))
  101.               (list 6 8 9 9))
  102.  
  103. (define (find-adjacent grid posn)
  104.   (map
  105.    (λ (p) (find-num-at-coordinates grid (add-posns posn p)))
  106.    ADJACENCY-LIST))
  107.  
  108. (define ADJACENCY-LIST (list (make-posn 0 -1)
  109.                              (make-posn -1 0)
  110.                              (make-posn 1 0)
  111.                              (make-posn 0 1)))
  112.  
  113. ;; add-posns : Position Position -> Position
  114. ;; adds the positions like vectors
  115.  
  116. (check-expect (add-posns (make-posn 1 2) (make-posn 0 0)) (make-posn 1 2))
  117. (check-expect (add-posns (make-posn 2 5) (make-posn -1 2)) (make-posn 1 7))
  118.  
  119. (define (add-posns posn1 posn2)
  120.   (make-posn (+ (posn-x posn1) (posn-x posn2))
  121.              (+ (posn-y posn1) (posn-y posn2))))
  122.          
  123. ;; find-num-at-coordinates : [List-of [List-of Number]] Position -> Number
  124. ;; returns the number at the coordinates or 9 if no such number exists
  125.  
  126. (check-expect (find-num-at-coordinates (list (list 1 2 3)
  127.                                              (list 4 5 6)
  128.                                              (list 7 8 9))
  129.                                        (make-posn 1 1))
  130.               5)
  131. (check-expect (find-num-at-coordinates (list (list 1 2 3)
  132.                                              (list 4 5 6)
  133.                                              (list 7 8 9))
  134.                                        (make-posn -1 1))
  135.               9)
  136.  
  137. (define (find-num-at-coordinates grid posn)
  138.   (local [(define HEIGHT (length grid))
  139.           (define WIDTH (length (first grid)))
  140.           (define X (posn-x posn))
  141.           (define Y (posn-y posn))]
  142.     (cond
  143.       [(or (negative? X) (>= X WIDTH)) 9]
  144.       [(or (negative? Y) (>= Y HEIGHT)) 9]
  145.       [else
  146.        (list-ref (list-ref grid Y) X)])))
  147.  
  148. ;; day 9 part 2
  149. ;; size of basins
  150.  
  151. ;; get-basin-size-product : String -> Number
  152. ;; gets the product of the sizes from the 3 largest basins
  153. ;; in the grid in the given file
  154.  
  155. (check-expect (get-basin-size-product "advent-smoke-1.txt") 1134)
  156.  
  157. (define (get-basin-size-product filename)
  158.   (local [(define GRID (los->grid (read-lines filename)))]
  159.     (foldr * 1
  160.            ((λ (L) (list (first L) (second L) (third L)))
  161.             (quicksort
  162.              (map
  163.               (λ (p) (find-size-of-basin GRID p))
  164.               (find-low-points GRID))
  165.              >=)))))
  166.  
  167. ;; find-size-of-basin : Grid Position -> Nat
  168. ;; given the grid and the lowest position in the basin,
  169. ;; how many numbers are in the basin
  170.  
  171. (check-expect (find-size-of-basin (list (list 0 1 9 0)
  172.                                         (list 2 9 2 1)
  173.                                         (list 3 9 9 5)
  174.                                         (list 9 0 1 9))
  175.                                   (make-posn 0 0))
  176.               4)
  177. (check-expect (find-size-of-basin (list (list 0 1 9 0)
  178.                                         (list 2 9 2 1)
  179.                                         (list 3 9 9 5)
  180.                                         (list 9 0 1 9))
  181.                                   (make-posn 3 0))
  182.               4)
  183. (check-expect (find-size-of-basin (list (list 0 1 9 0)
  184.                                         (list 2 9 2 1)
  185.                                         (list 3 9 9 5)
  186.                                         (list 9 0 1 9))
  187.                                   (make-posn 1 3))
  188.               2)
  189.  
  190. (define (find-size-of-basin grid lowest)
  191.   (local [;; find-posns-above : Position Number -> [List-of Position]
  192.           ;; given a position and the height of the previous position,
  193.           ;; if the current position is above the previous position
  194.           ;; returns a list of the current positions and all positions
  195.           ;; above it, stopping at and excluding positions with height 9.
  196.           (define (find-posns-above posn prev-height)
  197.             (local [(define HEIGHT (find-num-at-coordinates grid posn))
  198.                     (define NEIGHBORS (map (λ (p) (add-posns posn p)) ADJACENCY-LIST))]
  199.               (cond
  200.                 [(or (= HEIGHT 9) (<= HEIGHT prev-height)) '()]
  201.                 [else
  202.                  (cons posn (foldr append '()
  203.                                    (map (λ (p) (find-posns-above p HEIGHT)) NEIGHBORS)))])))
  204.  
  205.           ;; remove-duplicate-posns : [List-of Position] -> [List-of Position]
  206.           ;; removes duplicate positions from the list
  207.           (define (remove-duplicate-posns lop)
  208.             (foldr
  209.              (λ (curr prev)
  210.                (cons curr
  211.                      (filter
  212.                       (λ (p) (not (and (= (posn-x p) (posn-x curr))
  213.                                        (= (posn-y p) (posn-y curr)))))
  214.                       prev)))
  215.              '()
  216.              lop))]
  217.     (length (remove-duplicate-posns (find-posns-above lowest -1)))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement