From 1d536e649ecc28220fb53d1c91dc67fb5eaee9ba Mon Sep 17 00:00:00 2001 From: Adrian Braemer <11058200+NobodysHero@users.noreply.github.com> Date: Mon, 10 Dec 2018 15:57:29 +0100 Subject: [PATCH] Day 10 Added solutions for day10. Also added function "build-set" to utilities.lisp. --- advent-of-code-2018.asd | 3 ++- day10.lisp | 45 +++++++++++++++++++++++++++++++++++++++++ utilities.lisp | 5 +++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 day10.lisp diff --git a/advent-of-code-2018.asd b/advent-of-code-2018.asd index d334571..6b92aab 100644 --- a/advent-of-code-2018.asd +++ b/advent-of-code-2018.asd @@ -17,4 +17,5 @@ (:file "day6") (:file "day7") (:file "day8") - (:file "day9"))) + (:file "day9") + (:file "day10"))) diff --git a/day10.lisp b/day10.lisp new file mode 100644 index 0000000..4efe26d --- /dev/null +++ b/day10.lisp @@ -0,0 +1,45 @@ +;;;; day10.lisp + +(in-package :advent-of-code-2018) + +(defun day10-parse-input () + (let ((input + (loop-line-by-line (puzzlepath "input10.txt") + :collect (ppcre:register-groups-bind ((#'parse-integer x y dx dy)) + ("position=<( ?-?\\d+), ( ?-?\\d+)> velocity=<( ?-?\\d+), ( ?-?\\d+)>" line) + (list x y dx dy))))) + (make-array (length input) :element-type 'list :initial-contents input))) + +(defun day10-step (points &optional (amount 1)) + (loop :for point :across points + :do (incf (first point) (* (third point) amount)) + :do (incf (second point) (* (fourth point) amount))) + points) + +(defun day10-boundary (points) + (loop :for (x y) :across points + :minimize x :into min-x + :maximize x :into max-x + :minimize y :into min-y + :maximize y :into max-y + :finally (return (list min-x min-y (- max-x min-x) (- max-y min-y))))) + +(defun day10-pretty-print (points) + (destructuring-bind (dx dy width height) (day10-boundary points) + (loop + :with positions := (build-set points :test 'equal :key (lambda (p) (cons (first p) (second p)))) + :for y :upto height + :do (loop :for x :upto width + :do (format t (if (gethash (cons (+ dx x) (+ dy y)) positions) "#" " "))) + :do (format t "~%")))) + +(defun day10 () + (loop :for points := (day10-parse-input) :then (day10-step points) + :for (nil nil width height) := (day10-boundary points) + :for last-area := nil :then area + :for area := (* width height) + :until (and last-area (> area last-area)) + :count t :into seconds + :finally (progn + (format t "After ~a seconds the following message appears:~%~%" (1- seconds)) + (day10-pretty-print (day10-step points -1))))) diff --git a/utilities.lisp b/utilities.lisp index 78ed6a9..9934ed1 100644 --- a/utilities.lisp +++ b/utilities.lisp @@ -53,3 +53,8 @@ :for value := (aref vector index) :when (> value max-val) :do (setf max-ind index max-val value) :finally (return (values max-ind max-val)))) + +(defun build-set (seq &key (test 'eql) (key #'identity)) + (let ((set (make-hash-table :test test))) + (map nil (lambda (k) (setf (gethash (funcall key k) set) t)) seq) + set))