;; 6:34 ;; 8:11 part 1 ;; 9:36 part 2 (ql:quickload '(fiveam arrows cl-ppcre)) (defparameter eg-vert "#...##..# #....#..# ..##..### #####.##. #####.##. ..##..### #....#..#") (defparameter eg-horizontal "#.##..##. ..#.##.#. ##......# ##......# ..#.##.#. ..##..##. #.#.##.#.") (defun count-differences (a b) (loop for x across a for y across (or b "") count (not (eq x y)))) (defun v-mirror (rows &optional (max-differences 0)) (loop for idx from 1 below (length rows) when (= max-differences (loop for above in (reverse (subseq rows 0 idx)) for below in (subseq rows idx) sum (count-differences above below))) do (return idx))) (defun h-mirror (rows &optional (max-differences 0)) (v-mirror (transpose-rows rows) max-differences)) (defun transpose-rows (rows) (arrows:-<> rows (mapcar #'string-to-octets <>) (apply #'map 'list (lambda (&rest vals) (coerce (mapcar #'code-char vals) 'string)) <>))) (fiveam:test partials (fiveam:is (= 4 (v-mirror (cl-ppcre:split "\\n" eg-vert)))) (fiveam:is (= 1 (v-mirror (cl-ppcre:split "\\n" eg-vert) 1))) (fiveam:is (null (v-mirror (cl-ppcre:split "\\n" eg-horizontal)))) (fiveam:is (= 3 (v-mirror (cl-ppcre:split "\\n" eg-horizontal) 1))) (fiveam:is (= 5 (h-mirror (cl-ppcre:split "\\n" eg-horizontal)))) (fiveam:is (null (h-mirror (cl-ppcre:split "\\n" eg-horizontal) 1)))) (defun solver (maps &optional (max-differences 0)) (let ((vertical-mirrors (delete nil (mapcar (lambda (m) (v-mirror m max-differences)) maps))) (horizontal-mirrors (delete nil (mapcar (lambda (m) (h-mirror m max-differences)) maps)))) (+ (* 100 (apply #'+ vertical-mirrors)) (apply #'+ horizontal-mirrors)))) (defun parse-input (file) (arrows:->> (uiop:read-file-string file) (cl-ppcre:split "\\n\\n") (mapcar (lambda (map) (cl-ppcre:split "\\n" map))))) (fiveam:test solutions (fiveam:is (= 405 (solver (parse-input "eg-in")))) (fiveam:is (= 400 (solver (parse-input "eg-in") 1))) (fiveam:is (= 35360 (solver (parse-input "input")))) (fiveam:is (= 36755 (solver (parse-input "input") 1)))) (fiveam:run!)