AoC'21, day 5, first problem rvc


First, consider only horizontal and vertical lines.

 $ cat 05a.rkt  
 #lang racket 
  
  
 (provide 
   example-data 
   read-input) 
  
  
 (require 
   (prefix-in aoc: "aoc.rkt") 
   (prefix-in utl: "../scheme/utl.rkt")) 
  
  
 (define (aoc05a . args) 
  
   ; Return the number of deep vent points in the given sea-floor 
   ; map.  If no map is given, use the contest problem input; 
   ; otherwise assume the argument is the string representation of 
   ; a problem input. 
  
   (deep-vent-point-count 
     (apply read-input args))) 
  
  
  
 (define (deep-vent-point-count sea-floor-map) 
  
   ; Return the number of deep vent points in the given sea-floor 
   ; map.  A vent point is deep when it belongs to more than one 
   ; vent. 
  
  
   (define (delta c1 c2) 
  
     ; Return the delta that steps from the first given value to 
     ; the second. 
  
     (utl:signum (- c2 c1))) 
  
  
   (define plotted-points (make-hash)) 
  
  
   (define (plot-point x y) 
  
     ; Add the point with the given coordinates to the points 
     ; plotted. 
  
     (let ((pt (list x y))) 
       (hash-set! plotted-points pt 
                  (+ (hash-ref plotted-points pt 0) 1)))) 
  
  
   (define (plot-line ep1 ep2) 
  
     ; Plot the points on the line from the first given coordinate 
     ; to the second (inclusive at both ends). 
  
     (let* ((x1 (car ep1)) 
            (y1 (cadr ep1)) 
            (x2 (car ep2)) 
            (y2 (cadr ep2)) 
            (delta-x (delta x1 x2)) 
            (delta-y (delta y1 y2))) 
  
       (when (or (zero? delta-x) (zero? delta-y)) 
         (do 
  
             ((x x1 (+ x delta-x)) 
              (y y1 (+ y delta-y)) 
              (n (+ (max (abs (- x2 x1)) (abs (- y2 y1))) 1) (- n 1))) 
              
             ((zero? n) #t) 
  
           (plot-point x y))))) 
  
  
   (for-each 
     (lambda (l) (plot-line (car l) (cadr l))) 
     sea-floor-map) 
  
   (foldl 
     (lambda (c s) (+ s (if (= c 1) 0 1))) 
     0 
     (hash-values plotted-points))) 
  
  
 (define  (read-input . arg) 
  
   ; Return the given sea-floor map.  If no map is given, use the 
   ; contest problem input; otherwise assume the argument is the 
   ; string representation of a problem input. 
  
   (map 
     (lambda (l) (list (aoc:read-comma-separated-numbers (car l)) 
                       (aoc:read-comma-separated-numbers (caddr l)))) 
     (car (aoc:aoc-read-input (if (null? arg) 5 (car arg)))))) 
  
  
 (module+ main 
  
   (aoc05a)) 
  
  
 (aoc:define-string example-data 
   "0,9 -> 5,9" 
   "8,0 -> 0,8" 
   "9,4 -> 3,4" 
   "2,2 -> 2,1" 
   "7,0 -> 7,4" 
   "6,4 -> 2,0" 
   "0,9 -> 2,9" 
   "3,4 -> 1,4" 
   "0,0 -> 8,8" 
   "5,5 -> 8,2" 
   ) 
  
 (define example-result 5) 
  
  
 (module+ test 
  
   (require rackunit) 
  
   (for-each 
  
     (lambda (p) (check-equal? (aoc05a (car p)) (cdr p))) 
  
     `(("0,0 -> 3,0" . 0) 
       ("0,0 -> 3,0\n0,0 -> 3,0" . 4) 
       (,example-data . ,example-result))) 
  
   (check-equal? (aoc05a) 5084) 
   ) 
  
 $ raco test 05a.rkt  
 raco test: (submod "05a.rkt" test) 
 4 tests passed 
  
 $