summaryrefslogtreecommitdiffstats
path: root/2021/19/code.tl
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-11-06 09:58:38 -0800
committerKaz Kylheku <kaz@kylheku.com>2022-11-06 09:58:38 -0800
commit4fd1aae518076adc8b97735225c678d6a362328d (patch)
tree97d61b659fc3cac628d0cdee71128a0baee2cb73 /2021/19/code.tl
downloadadvent-4fd1aae518076adc8b97735225c678d6a362328d.tar.gz
advent-4fd1aae518076adc8b97735225c678d6a362328d.tar.bz2
advent-4fd1aae518076adc8b97735225c678d6a362328d.zip
Kazinator's Advent of Code stuff.
Diffstat (limited to '2021/19/code.tl')
-rw-r--r--2021/19/code.tl164
1 files changed, 164 insertions, 0 deletions
diff --git a/2021/19/code.tl b/2021/19/code.tl
new file mode 100644
index 0000000..97dd3f3
--- /dev/null
+++ b/2021/19/code.tl
@@ -0,0 +1,164 @@
+(defstruct scanner ()
+ id
+ data
+ rot
+ pref
+ delta
+ nei)
+
+(defun read-input (: (name "input"))
+ (with-stream (s (open-file name))
+ (build
+ (let (scnr)
+ (while-match-case (get-line s)
+ ("")
+ (`@x,@y,@z` (push (vec (toint x) (toint y) (toint z)) scnr.data))
+ (`--- scanner @n ---` (set scnr (new scanner id (toint n))) (add scnr)))))))
+
+(defmacro x (p) ^[,p 0])
+(defmacro y (p) ^[,p 1])
+(defmacro z (p) ^[,p 2])
+
+(defmacro rot-z (p)
+ (with-gensyms (tp)
+ ^(let ((,tp ,p))
+ (vec (- (y ,tp)) (x ,tp) (z ,tp)))))
+
+(defmacro rot-y (p)
+ (with-gensyms (tp)
+ ^(let ((,tp ,p))
+ (vec (z ,tp) (y ,tp) (- (x ,tp))))))
+
+(defmacro rot-x (p)
+ (with-gensyms (tp)
+ ^(let ((,tp ,p))
+ (vec (x ,tp) (- (z ,tp)) (y ,tp)))))
+
+(defmacro psub (p0 p1)
+ (with-gensyms (tp0 tp1)
+ ^(let ((,tp0 ,p0) (,tp1 ,p1))
+ (vec (- (x ,tp0) (x ,tp1))
+ (- (y ,tp0) (y ,tp1))
+ (- (z ,tp0) (z ,tp1))))))
+
+(defmacro padd (p0 p1)
+ (with-gensyms (tp0 tp1)
+ ^(let ((,tp0 ,p0) (,tp1 ,p1))
+ (vec (+ (x ,tp0) (x ,tp1))
+ (+ (y ,tp0) (y ,tp1))
+ (+ (z ,tp0) (z ,tp1))))))
+
+(defmeth scanner gen-rot (sc)
+ (set sc.rot (vec))
+ (dotimes (i 24)
+ (vec-push sc.rot (vec)))
+
+ (each ((rA sc.data))
+ (let* ( (rB (rot-x rA)) (rC (rot-x rB)) (rD (rot-x rC))
+ (rE (rot-z rA)) (rF (rot-y rE)) (rG (rot-y rF)) (rH (rot-y rG))
+ (rI (rot-z rE)) (rJ (rot-x rI)) (rK (rot-x rJ)) (rL (rot-x rK))
+ (rM (rot-z rI)) (rN (rot-y rM)) (rO (rot-y rN)) (rP (rot-y rO))
+ (rQ (rot-y rA)) (rR (rot-z rQ)) (rS (rot-z rR)) (rT (rot-z rS))
+ (rU (rot-y (rot-y rQ))) (rV (rot-z rU)) (rW (rot-z rV)) (rX (rot-z rW)))
+ (vec-push [sc.rot 0] rA) (vec-push [sc.rot 1] rB)
+ (vec-push [sc.rot 2] rC) (vec-push [sc.rot 3] rD)
+ (vec-push [sc.rot 4] rE) (vec-push [sc.rot 5] rF)
+ (vec-push [sc.rot 6] rG) (vec-push [sc.rot 7] rH)
+ (vec-push [sc.rot 8] rI) (vec-push [sc.rot 9] rJ)
+ (vec-push [sc.rot 10] rK) (vec-push [sc.rot 11] rL)
+ (vec-push [sc.rot 12] rM) (vec-push [sc.rot 13] rN)
+ (vec-push [sc.rot 14] rO) (vec-push [sc.rot 15] rP)
+ (vec-push [sc.rot 16] rQ) (vec-push [sc.rot 17] rR)
+ (vec-push [sc.rot 18] rS) (vec-push [sc.rot 19] rT)
+ (vec-push [sc.rot 20] rU) (vec-push [sc.rot 21] rV)
+ (vec-push [sc.rot 22] rW) (vec-push [sc.rot 23] rX))))
+
+(defun overlap-delta (pvec0 pvec1 amt)
+ (each-prod ((p0 pvec0)
+ (p1 pvec1))
+ (let* ((delta (psub p1 p0))
+ (novl (len (isec pvec0
+ (mapcar (do psub @1 delta) pvec1)))))
+ (when (>= novl amt)
+ (return delta)))))
+
+(defun overlaps-with (s0 s1 : (amt 12))
+ (for* ((r 0) (r0 [s0.rot (or s0.pref 0)]) (rot1 s1.rot) (n (len rot1)))
+ ((< r n))
+ ((inc r))
+ (whenlet ((delta (overlap-delta r0 [rot1 r] amt)))
+ (return (cons delta r)))))
+
+(defun link-graph (slist)
+ (let ((sf (car slist))
+ (backref)
+ (count 0))
+ (flet ((lnk (s0 s1)
+ (tree-case (overlaps-with s0 s1)
+ ((delta . r)
+ (prinl ^(:lap ,s0.id ,s1.id ,r ,delta))
+ (cond
+ ((and (neq s0 sf) (null s0.pref))
+ (push (cons s0 s1) backref))
+ (t
+ (set s1.pref r)
+ (push (list* s1 r delta) s0.nei)))))))
+ (each-match ((@s0 @s1) (comb slist 2))
+ (prinl ^(,(inc count) ,s0.id ,s1.id))
+ (cond
+ ((null s1.pref) (lnk s0 s1))
+ ((null s0.pref) (lnk s1 s0))))
+ (while backref
+ (set count 0)
+ (put-line "backref")
+ (each-match ((@s0 . @s1) (zap backref))
+ (prinl ^(,(inc count) ,s0.id ,s1.id))
+ (cond
+ ((null s1.pref) (lnk s0 s1))
+ ((null s0.pref) (lnk s1 s0))))))
+ (keep-if .nei slist)))
+
+(defun assemble-map (slist)
+ (let ((out (vec)))
+ (labels ((visit (sn r delta)
+ (prinl ^(:visit ,sn.id ,r))
+ (set sn.delta delta)
+ (each ((p [sn.rot r]))
+ (vec-push out (psub p delta)))
+ (each-match ((@n @nr . @ndelta) sn.nei)
+ (visit n nr (padd delta ndelta)))))
+ (visit (car slist) 0 #(0 0 0)))
+ (prinl ^(:len out ,(len out)))
+ (uniq out)))
+
+;; answer is 438
+(defun solve-one (: (name :))
+ (flow name
+ read-input
+ (progn (mapdo .(gen-rot) @1) @1)
+ link-graph
+ assemble-map))
+
+(defun manhattan (p)
+ [sum p abs])
+
+(defun max-manhattan-delta (slist)
+ (let ((maxhattan 0))
+ (each-match ((@s0 @s1) (comb slist 2))
+ (prinl ^(:delta ,s0.id ,s0.delta ,s1.id ,s1.delta))
+ (let ((mhdelta (manhattan (psub s0.delta s1.delta))))
+ (upd maxhattan (max mhdelta))))
+ maxhattan))
+
+;; answer is 11985
+(defun solve-two (: (name :))
+ (flow name
+ read-input
+ (let ((orig @1))
+ (flow orig
+ (progn (mapdo .(gen-rot) @1) @1)
+ link-graph
+ assemble-map)
+ (flow orig
+ (keep-if .delta)
+ max-manhattan-delta))))