~shunter/advent2021

7638698246c008bc636f43de399b34c1283a6101 — Samuel Hunter 2 years ago cf69cf5
Refactor Day 05
1 files changed, 22 insertions(+), 39 deletions(-)

M day05.lisp
M day05.lisp => day05.lisp +22 -39
@@ 14,40 14,23 @@
                (mapcar #'parse-integer (split "," s)))
              (split " -> " line)))))

;; Brute-force all combinations, time typing was cheaper than time thinking
;; about a more elegant way to do this.
(defun walk-line (function line count-diagonals)
(defun walk-line (function line)
  (destructuring-bind (x1 y1 x2 y2) line
    (cond
      ((and (= x1 x2) (<= y1 y2))
       (loop :for y :from y1 :to y2
             :do (funcall function x1 y)))
      ((= x1 x2)
       (loop :for y :from y1 :downto y2
             :do (funcall function x1 y)))
      ((and (= y1 y2) (<= x1 x2))
       (loop :for x :from x1 :to x2
             :do (funcall function x y1)))
      ((= y1 y2)
       (loop :for x :from x1 :downto x2
             :do (funcall function x y1)))
      (count-diagonals) ;; skip diagonals here
      ((and (<= x1 x2) (<= y1 y2))
       (loop :for x :from x1 :to x2
             :for y :from y1 :to y2
             :do (funcall function x y)))
      ((and (<= x1 x2))
       (loop :for x :from x1 :to x2
             :for y :from y1 :downto y2
             :do (funcall function x y)))
      ((and (<= y1 y2))
       (loop :for x :from x1 :downto x2
             :for y :from y1 :to y2
             :do (funcall function x y)))
      (t
       (loop :for x :from x1 :downto x2
             :for y :from y1 :downto y2
             :do (funcall function x y))))))
    (loop :with dx := (signum (- x2 x1))
          :with dy := (signum (- y2 y1))

          :for x := x1 :then (+ x dx)
          :for y := y1 :then (+ y dy)

          :do (funcall function x y)
          :until (and (= x x2) (= y y2)))))

(defmacro do-line ((x y) line &body body)
  `(walk-line (lambda (,x ,y) ,@body) ,line))

(defun is-orthographic (line)
  (destructuring-bind (x1 y1 x2 y2) line
    (or (= x1 x2) (= y1 y2))))

(defun max-dimensions ()
  (loop :for (x1 y1 x2 y2) :in +input+


@@ 55,20 38,20 @@
        :maximize (max y1 y2) :into y
        :finally (return (list (1+ x) (1+ y)))))

(defun solve (count-diags)
(defun solve (count-diagonals)
  (loop :with (w h) := (max-dimensions)
        :with grid := (make-array (list h w) :element-type 'integer)
        :for line :in +input+
        :do (walk-line (lambda (x y)
                         (incf (aref grid y x)))
                       line count-diags)
        :when (or (is-orthographic line) count-diagonals)
          :do (do-line (x y) line
                (incf (aref grid y x)))
        :finally (return
                   (loop :for x :below w
                         :sum (loop :for y :below h
                                    :count (> (aref grid y x) 1))))))

(defun solve-part-1 ()
  (solve t))
  (solve nil))

(defun solve-part-2 ()
  (solve nil))
  (solve t))