Commit Diff


commit - db0986abd6d2a985fff0dd0baa13c97a708a6b53
commit + b70c7b2a5c6627168ec3652c3841e54b97f55bc5
blob - 2581bbf42a23ab0703f8ed0f2e3430b5baf0cf7c
blob + 11e0cb5285eaea4533dd1d30386b6476f5ab0bd3
--- src/day-4.lisp
+++ src/day-4.lisp
@@ -9,7 +9,7 @@
                   for new-point = (point+ point (cons (* nx m)
                                                       (* ny m)))
                   for cell = nil
-                  unless (point-in-bounds-p new-point map)
+                  unless (point-in-map-p new-point map)
                     do (return 0)
                   do (setf cell (map-cell map new-point))
                   unless (char= cell char)
@@ -19,7 +19,7 @@
 (defun mas-p (map point t-x)
   (let ((ps (list (point+ point (cons t-x -1))
                   (point+ point (cons (* t-x -1) 1)))))
-    (unless (every (rcurry #'point-in-bounds-p map) ps)
+    (unless (every (rcurry #'point-in-map-p map) ps)
       (return-from mas-p nil))
     (let ((cs (mapcar (curry #'map-cell map) ps)))
       (and (member #\M cs)
blob - 2a21094e0eeba156116e0da9544abf12ddad2d62
blob + a2d5c00afce087e744984dba77dfb8e4a6a5b65a
--- src/day-6.lisp
+++ src/day-6.lisp
@@ -27,44 +27,72 @@
     (:down :left)
     (:left :up)))
 
-(defun walk-map (map pos)
+(declaim (ftype (function (fixnum fixnum) (simple-array t (* * 4))) make-visited-cache))
+(defun make-visited-cache (width height)
+  (make-array (list width height 4)
+              :initial-element nil))
+
+(declaim (inline visited-p
+                 (setf visited-p)))
+
+(defun visited-p (cache point dir)
+  (destructuring-bind (x . y) point
+    (aref cache x y (ecase dir
+                      (:up 0)
+                      (:left 1)
+                      (:right 2)
+                      (:down 3)))))
+
+(defun (setf visited-p) (new-value cache point dir)
+  (destructuring-bind (x . y) point
+    (setf (aref cache x y (ecase dir
+                            (:up 0)
+                            (:left 1)
+                            (:right 2)
+                            (:down 3)))
+          new-value)))
+
+(defun walk-map (map pos &optional check-loops)
   (loop with dir = :up
-        with visited = (list pos)
-        with visited-dir = (make-hash-table :test #'equal)
         with map-width = (input-map-width map)
         with map-height = (input-map-height map)
-        with in-bounds-p = (lambda (point)
-                             (and (>= (point-x point) 0)
-                                  (>= (point-y point) 0)
-                                  (< (point-x point) map-width)
-                                  (< (point-y point) map-height)))
-        while (funcall in-bounds-p pos)
-        when (gethash (cons pos dir) visited-dir)
+        with visited-dir = (make-visited-cache map-width map-height)
+        with visited = (make-array (list map-width map-height)
+                                   :initial-element nil)
+        with count-visited fixnum = 0
+        while (point-in-bounds-p pos map-width map-height)
+        when (and check-loops (visited-p visited-dir pos dir))
           do (return :loop)
-        do (setf (gethash (cons pos dir) visited-dir) t
-                 pos (loop with next = (next pos dir)
-                           while (and (funcall in-bounds-p next)
+        when check-loops
+          do (setf (visited-p visited-dir pos dir) t)
+        do (destructuring-bind (x . y) pos
+             (unless (aref visited x y)
+               (incf count-visited)
+               (setf (aref visited x y) t)))
+           (setf pos (loop with next = (next pos dir)
+                           while (and (point-in-bounds-p next map-width map-height)
                                       (char= (map-cell map next) #\#))
                            do (setf dir (turn dir)
                                     next (next pos dir))
                            finally (return next)))
-           (push pos visited)
-        finally (return (remove-duplicates (cdr visited) :test #'equal))))
+        finally (return (values count-visited visited))))
 
 (defun task-2 (map initial-pos visited)
   (loop with task-2 = 0
-        for point in visited
-        for cell = (map-cell map point)
-        when (char= cell #\.)
-          do (setf (map-cell map point) #\#)
-             (when (eq (walk-map map initial-pos) :loop)
-               (incf task-2))
-             (setf (map-cell map point) #\.)
+        for x from 0 below (input-map-width map)
+        do (loop for y from 0 below (input-map-height map)
+                 for point = (cons x y)
+                 when (and (aref visited x y)
+                           (char= (map-cell map point) #\.))
+                   do (setf (map-cell map point) #\#)
+                      (when (eq (walk-map map initial-pos t) :loop)
+                        (incf task-2))
+                      (setf (map-cell map point) #\.))
         finally (return task-2)))
 
 (defun day-6 (input)
   (let* ((map (make-map input))
-         (pos (find-guard map))
-         (visited (walk-map map pos)))
-    (values (length visited)
-            (task-2 map pos visited))))
+         (pos (find-guard map)))
+    (multiple-value-bind (task-1 visited)
+        (walk-map map pos)
+      (values task-1 (task-2 map pos visited)))))
blob - d3f56b7b9d5baa494ed91d7dcc2613b68c73759b
blob + 00e6faee0cb4741ff8e503edbc2b909101f28dbd
--- src/utils.lisp
+++ src/utils.lisp
@@ -21,6 +21,7 @@
    #:point-x
    #:point-y
    #:point-in-bounds-p
+   #:point-in-map-p
    #:*map-neighbours*
    #:point-neighbours
    #:manhattan-distance
@@ -136,12 +137,17 @@
         (the fixnum (- (point-y point-a)
                        (point-y point-b)))))
 
-(defun point-in-bounds-p (point map)
-  (and (>= (point-x point) 0)
-       (>= (point-y point) 0)
-       (< (point-x point) (input-map-width map))
-       (< (point-y point) (input-map-height map))))
+(declaim (inline point-in-bounds-p point-in-map-p))
+(defun point-in-bounds-p (point width height)
+  (destructuring-bind (x . y) point
+    (and (>= x 0) (>= y 0)
+         (< x width) (< y height))))
 
+(defun point-in-map-p (point map)
+  (point-in-bounds-p point
+                     (input-map-width map)
+                     (input-map-height map)))
+
 (declaim (inline map-cell map-integer-at (setf map-cell))
          (ftype (function (input-map cons) character) map-cell)
          (ftype (function (character input-map cons) character) (setf map-cell)))