solved day 14
This commit is contained in:
parent
45e33c3438
commit
bcab2ab698
2 changed files with 182 additions and 20 deletions
|
@ -1,7 +1,13 @@
|
|||
|
||||
(defpackage :aoc/2024/14
|
||||
(:use :cl :aoc :alexandria :trivia :lla)
|
||||
(:use :cl :aoc :alexandria :lla :ppcre)
|
||||
(:export
|
||||
#:parse-line
|
||||
#:make-robot
|
||||
#:quadrant
|
||||
#:robot-at-position
|
||||
#:robot-at-time
|
||||
#:safety-factor
|
||||
#:sample-text
|
||||
#:sample-data
|
||||
#:sample-data2
|
||||
#:part1
|
||||
|
@ -10,9 +16,46 @@
|
|||
|
||||
(in-package :aoc/2024/14)
|
||||
|
||||
(defstruct robot px py vx vy)
|
||||
|
||||
(defun robot-position (r)
|
||||
(vector (robot-px r) (robot-py r)))
|
||||
|
||||
(defun robot-velocity (r)
|
||||
(vector (robot-vx r) (robot-vy r)))
|
||||
|
||||
(defun robot-at-position (r p)
|
||||
(let* ((v (robot-velocity r)))
|
||||
(make-robot
|
||||
:px (aref p 0)
|
||||
:py (aref p 1)
|
||||
:vx (aref v 0)
|
||||
:vy (aref v 1)
|
||||
)))
|
||||
|
||||
(defun robot-at-time (r n grid)
|
||||
(let* ((p (robot-position r))
|
||||
(v (robot-velocity r))
|
||||
(np (aops:vectorize (p v grid)
|
||||
(mod (+ p (* n v)) grid))))
|
||||
(make-robot
|
||||
:px (aref np 0)
|
||||
:py (aref np 1)
|
||||
:vx (aref v 0)
|
||||
:vy (aref v 1)
|
||||
)))
|
||||
|
||||
(defun parse-line (line)
|
||||
line)
|
||||
(let ((numbers nil))
|
||||
(do-matches-as-strings
|
||||
(s "-?\\d+" line)
|
||||
(push (parse-integer s) numbers))
|
||||
(make-robot
|
||||
:px (nth 3 numbers)
|
||||
:py (nth 2 numbers)
|
||||
:vx (nth 1 numbers)
|
||||
:vy (nth 0 numbers)
|
||||
)))
|
||||
|
||||
|
||||
(defun parse-input (lines)
|
||||
|
@ -21,15 +64,113 @@
|
|||
(defparameter input-text (test-input 2024 14))
|
||||
(defparameter input-data (parse-input input-text))
|
||||
|
||||
(defparameter sample-text (aoc:split-lines ""))
|
||||
(defparameter sample-data
|
||||
(parse-input sample-text))
|
||||
(defparameter sample-text (aoc:split-lines "p=0,4 v=3,-3
|
||||
p=6,3 v=-1,-3
|
||||
p=10,3 v=-1,2
|
||||
p=2,0 v=2,-1
|
||||
p=0,0 v=1,3
|
||||
p=3,0 v=-2,-2
|
||||
p=7,6 v=-1,-3
|
||||
p=3,0 v=-1,-2
|
||||
p=9,3 v=2,3
|
||||
p=7,3 v=-1,2
|
||||
p=2,4 v=2,-3
|
||||
p=9,5 v=-3,-3
|
||||
"))
|
||||
|
||||
(defun part1 (data)
|
||||
(length data))
|
||||
(defparameter sample-data
|
||||
(parse-input sample-text))
|
||||
|
||||
|
||||
(defun quadrant (position gridsize)
|
||||
(let ((mx (/ (1- (aref gridsize 0)) 2))
|
||||
(my (/ (1- (aref gridsize 1)) 2))
|
||||
(x (aref position 0))
|
||||
(y (aref position 1)))
|
||||
(if (or (= x mx) (= y my))
|
||||
nil
|
||||
(+
|
||||
(if (< x mx) 0 1)
|
||||
(if (< y my) 0 2)))))
|
||||
|
||||
(defun robots-at-time (robots n grid)
|
||||
(mapcar
|
||||
(lambda (r) (robot-at-time r n grid))
|
||||
robots))
|
||||
|
||||
(defun map-robots (robots gridsize)
|
||||
|
||||
(let ((map (make-array (reverse (coerce gridsize 'list)) :initial-element 0)))
|
||||
(loop
|
||||
for r in robots
|
||||
do (incf (aref map (robot-py r) (robot-px r))))
|
||||
map))
|
||||
|
||||
(defun show-robots (robots gridsize)
|
||||
(defun render (n)
|
||||
(if (= n 0) "." (format nil "~A" n)))
|
||||
(let ((map (map-robots robots gridsize)))
|
||||
(loop
|
||||
for y from 0 below (array-dimension map 0)
|
||||
do (loop
|
||||
for x from 0 below (array-dimension map 1)
|
||||
do (format t "~A" (render (aref map y x))))
|
||||
do (format t "~%"))))
|
||||
|
||||
(defun safety-factor (robots grid)
|
||||
|
||||
(let ((qs (make-array '(4) :initial-element 0))
|
||||
(rp-100 (lambda (r) (robot-at-time r 100 grid))))
|
||||
(loop
|
||||
for p in (mapcar rp-100 robots)
|
||||
for q = (quadrant (robot-position p) grid)
|
||||
if q
|
||||
do (incf (aref qs q))
|
||||
finally
|
||||
(return (aops:vectorize-reduce #'* (qs) (identity qs))))))
|
||||
|
||||
(defun robots-symmetry-score (robots grid)
|
||||
(let ((m (map-robots robots grid)))
|
||||
(loop
|
||||
for y from 0 below (array-dimension m 0)
|
||||
sum (loop
|
||||
for x1 from 0 below (/ (1- (array-dimension m 1)) 2)
|
||||
for x2 from (1- (array-dimension m 1)) downto 0
|
||||
sum (if (and
|
||||
(not (zerop (aref m y x1)))
|
||||
(not (zerop (aref m y x2))))
|
||||
1 0)
|
||||
))))
|
||||
|
||||
(defun sqr (x) (* x x))
|
||||
(defun robots-variance-score (robots grid)
|
||||
(let* ((n (length robots))
|
||||
(mx (/ (loop for r in robots sum (robot-px r)) n))
|
||||
(my (/ (loop for r in robots sum (robot-py r)) n))
|
||||
(vx (/ (loop for r in robots sum (sqr (- (robot-px r) mx))) n))
|
||||
(vy (/ (loop for r in robots sum (sqr (- (robot-py r) my))) n)))
|
||||
(list (round mx) (round my) (sqrt vx) (sqrt vy))))
|
||||
|
||||
(defun find-t-with-symmetry-higher (max-t min-symmetry robots grid)
|
||||
(loop for n from 0 to max-t
|
||||
for score = (robots-symmetry-score (robots-at-time robots n grid) grid)
|
||||
if (> score min-symmetry)
|
||||
collect n))
|
||||
|
||||
(defun first-t-with-variance-lower (max-t max-s robots grid)
|
||||
(loop for n from 0 to max-t
|
||||
for score = (robots-variance-score (robots-at-time robots n grid) grid)
|
||||
for sx = (nth 2 score)
|
||||
for sy = (nth 3 score)
|
||||
until (and (< sx max-s) (< sy max-s))
|
||||
finally (return (list n sx sy))))
|
||||
|
||||
(defun part1 (data &optional (grid #(101 103)))
|
||||
(format nil "~A" (safety-factor data grid)))
|
||||
|
||||
(defun part2 (data)
|
||||
(length data))
|
||||
(let ((stats (first-t-with-variance-lower 50000 20 data #(101 103))))
|
||||
(format nil "~A" (first stats))))
|
||||
|
||||
(defun solve-day ()
|
||||
(format t "part1: ~A~%" (part1 input-data))
|
||||
|
|
|
@ -7,21 +7,42 @@
|
|||
;:parent suite-2024
|
||||
)
|
||||
|
||||
(define-test test-foo
|
||||
:parent suite-2024-14
|
||||
)
|
||||
(define-test test-parse-line
|
||||
:parent suite-2024-14
|
||||
(is equalp (make-robot :px 0 :py 4 :vx 3 :vy -3) (parse-line "p=0,4 v=3,-3" ))
|
||||
)
|
||||
|
||||
(define-test test-robot-position
|
||||
:parent suite-2024-14
|
||||
(let ((r (make-robot :px 2 :py 4 :vx 2 :vy -3))
|
||||
(g #(11 7)))
|
||||
(is equalp (robot-at-position r #(4 1)) (robot-at-time r 1 g))
|
||||
(is equalp (robot-at-position r #(6 5)) (robot-at-time r 2 g))
|
||||
(is equalp (robot-at-position r #(8 2)) (robot-at-time r 3 g))
|
||||
(is equalp (robot-at-position r #(10 6)) (robot-at-time r 4 g))
|
||||
(is equalp (robot-at-position r #(1 3)) (robot-at-time r 5 g))
|
||||
(is equalp (robot-at-position r #(4 5)) (robot-at-time r 100 g))
|
||||
))
|
||||
|
||||
(define-test test-bar
|
||||
:parent suite-2024-14
|
||||
)
|
||||
(define-test test-quadrant
|
||||
:parent suite-2024-14
|
||||
(false (quadrant #(5 1) #(11 7)))
|
||||
(false (quadrant #(8 3) #(11 7)))
|
||||
(is = 0 (quadrant #(0 0) #(11 7)))
|
||||
(is = 1 (quadrant #(7 2) #(11 7)))
|
||||
(is = 2 (quadrant #(4 4) #(11 7)))
|
||||
(is = 3 (quadrant #(6 4) #(11 7)))
|
||||
)
|
||||
|
||||
(define-test test-safety-factor
|
||||
:parent suite-2024-14
|
||||
(is = 12 (safety-factor sample-data #(11 7)))
|
||||
)
|
||||
|
||||
|
||||
|
||||
(define-test+run test-part1
|
||||
:parent suite-2024-14
|
||||
(is equal nil (part1 sample-data)))
|
||||
:parent suite-2024-14
|
||||
(is equal "12" (part1 sample-data #(11 7))))
|
||||
|
||||
|
||||
(define-test+run test-part2
|
||||
:parent suite-2024-14
|
||||
(is equal nil (part2 sample-data)))
|
||||
|
|
Loading…
Reference in a new issue