commit - f379ab53ea1596b4051f8162e1df4a267c92e47d
commit + c3dc0bc1b9d10e1cb15b5e7b3de92896523afbb5
blob - cdc218e1f7503f21d26b948ae8e92aff9766c49b
blob + eb6aa41de116b76751c296c92e52e2364779df10
--- src/day-14.lisp
+++ src/day-14.lisp
(:export #:day-14))
(in-package #:aoc/day-14)
-(defun slide-rock (map pos)
- (loop for y from (1- (point-y pos)) downto 0
- for cell = (map-cell map (cons (point-x pos) y))
- while (char= cell #\.)
- finally (setf (map-cell map pos) #\.
- (map-cell map (cons (point-x pos) (1+ y))) #\O)))
+(defun point-x-constructor (y)
+ (lambda (x)
+ (cons x y)))
-(defun slide-rocks (map)
- (loop for y from 0 below (input-map-height map)
- do (loop for x from 0 below (input-map-height map)
- for pos = (cons x y)
- for cell = (map-cell map pos)
- when (char= cell #\O)
- do (slide-rock map pos))))
+(defun point-y-constructor (x)
+ (lambda (y)
+ (cons x y)))
+(defun make-in-range-p (to)
+ (lambda (i)
+ (and (>= i 0)
+ (< i to))))
+
+(defun slide-rock-direction-configuration (map point direction)
+ (ecase direction
+ (:north
+ (values (1- (point-y point))
+ #'1- #'1+
+ (make-in-range-p (input-map-height map))
+ (point-y-constructor (point-x point))))
+ (:west
+ (values (1- (point-x point))
+ #'1- #'1+
+ (make-in-range-p (input-map-width map))
+ (point-x-constructor (point-y point))))
+ (:south
+ (values (1+ (point-y point))
+ #'1+ #'1-
+ (make-in-range-p (input-map-height map))
+ (point-y-constructor (point-x point))))
+ (:east
+ (values (1+ (point-x point))
+ #'1+ #'1-
+ (make-in-range-p (input-map-width map))
+ (point-x-constructor (point-y point))))))
+
+(defun slide-rock (map pos direction)
+ (multiple-value-bind (start-pos by final in-range-p make-point)
+ (slide-rock-direction-configuration map pos direction)
+ (loop for i = start-pos then (funcall by i)
+ while (funcall in-range-p i)
+ for cell = (map-cell map (funcall make-point i))
+ while (char= cell #\.)
+ finally (setf (map-cell map pos) #\.
+ (map-cell map (funcall make-point (funcall final i))) #\O))))
+
+(defun slide-direction-configuration (map direction)
+ (ecase direction
+ (:north
+ (values 0 #'1+
+ (curry #'> (input-map-height map)) (input-map-width map)
+ (lambda (d-1 d-2)
+ (cons d-2 d-1))))
+ (:west
+ (values 0 #'1+
+ (curry #'> (input-map-width map)) (input-map-height map)
+ (lambda (d-1 d-2)
+ (cons d-1 d-2))))
+ (:south
+ (values (1- (input-map-height map)) #'1-
+ (curry #'<= 0) (input-map-width map)
+ (lambda (d-1 d-2)
+ (cons d-2 d-1))))
+ (:east
+ (values (1- (input-map-width map)) #'1-
+ (curry #'<= 0) (input-map-height map)
+ (lambda (d-1 d-2)
+ (cons d-1 d-2))))))
+
+(defun slide-rocks (map direction)
+ (multiple-value-bind (d-1-from d-1-by d-1-while-p d-2-below make-point)
+ (slide-direction-configuration map direction)
+ (loop for d-1 = d-1-from then (funcall d-1-by d-1)
+ while (funcall d-1-while-p d-1)
+ do (loop for d-2 from 0 below d-2-below
+ for pos = (funcall make-point d-1 d-2)
+ for cell = (map-cell map pos)
+ when (char= cell #\O)
+ do (slide-rock map pos direction)))))
+
(defun total-load (map)
(loop for y from 0 below (input-map-height map)
for load-multiplier downfrom (input-map-height map)
(defun day-14 (input)
(let ((map (make-map input)))
- (slide-rocks map)
+ (slide-rocks map :north)
(total-load map)))