commit - c3dc0bc1b9d10e1cb15b5e7b3de92896523afbb5
commit + c1af0e38b7b56e77082a3f44eaa249842a057535
blob - eb6aa41de116b76751c296c92e52e2364779df10
blob + 5e22aada04da225e73955a5d23c96538b55149fd
--- src/day-14.lisp
+++ src/day-14.lisp
(defpackage #:aoc/day-14
(:use #:cl #:aoc/utils)
- (:export #:day-14))
+ (:export
+ #:day-14
+ #:*minimum-pattern-length*))
(in-package #:aoc/day-14)
(defun point-x-constructor (y)
when (char= (map-cell map (cons x y)) #\O)
sum load-multiplier)))
+(defun spin-cycle (map &optional (cycle '(:north :west :south :east)))
+ (loop for direction in cycle
+ do (slide-rocks map direction)))
+
+(defparameter *minimum-pattern-length* 100)
+
(defun day-14 (input)
- (let ((map (make-map input)))
+ (let ((map (make-map input))
+ task-1 task-2)
(slide-rocks map :north)
- (total-load map)))
+ (setf task-1 (total-load map))
+ (spin-cycle map '(:west :south :east))
+ (loop with history = nil
+ for cycles from 1
+ do (spin-cycle map)
+ do (push (total-load map) history)
+ do (let ((pattern-length (find-pattern history *minimum-pattern-length*)))
+ (when pattern-length
+ (setf task-2
+ (elt history
+ (1+ (- pattern-length
+ (- (mod 1000000000 pattern-length)
+ (- cycles (* pattern-length 2)))))))
+ (return))))
+ (values task-1 task-2)))
blob - 77b9695adb09e11531523101ac2139a83dba208d
blob + 4cb420b7bb4d2867654f0ba805b6e4d9358f268d
--- src/utils.lisp
+++ src/utils.lisp
#:point-neighbours
#:manhattan-distance
#:do-map-neighbours
- #:read-number-list))
+ #:read-number-list
+ #:find-pattern))
(in-package #:aoc/utils)
(defun normalize-type (type)
:junk-allowed t)
(setf i end)
number)))
+
+(defun find-pattern (list &optional (minimum-length 5))
+ (loop for length from minimum-length to (floor (/ (length list) 2))
+ when (loop for i below length
+ for c-1 = (elt list i)
+ for c-2 = (elt list (+ i length))
+ always (= c-1 c-2))
+ do (return-from find-pattern length)))
blob - 674d3e70818397bead7fd08ea24a375d792df4bf
blob + bc301508974173263f53c6a3f0e089cefb438bfd
--- t/day-14.lisp
+++ t/day-14.lisp
(define-test test-day-14
()
- (multiple-value-bind (task-1)
- (aoc:run-day 14 "O....#....
+ (let ((aoc/day-14:*minimum-pattern-length* 5))
+ (multiple-value-bind (task-1 task-2)
+ (aoc:run-day 14 "O....#....
O.OO#....#
.....##...
OO.#O....O
.......O..
#....###..
#OO..#....")
- (assert= 136 task-1)))
+ (assert= 136 task-1)
+ (assert= 64 task-2))))