advent-of-code-2024

My solutions to AoC 2024
Log | Files | Refs

commit 97d18b948329b91bd9148c09f1b4b6b0bcbe8f6a
parent 457f75706b34cdea7df3379f1bd773fc398e17fd
Author: Lukas Henkel <lh@entf.net>
Date:   Tue, 24 Dec 2024 17:16:46 +0100

Day 24

Well, this works for my input

Diffstat:
Ainput/24.txt | 313+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/day-24.lisp | 136+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
At/day-24.lisp | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 503 insertions(+), 0 deletions(-)

diff --git a/input/24.txt b/input/24.txt @@ -0,0 +1,313 @@ +x00: 1 +x01: 1 +x02: 0 +x03: 0 +x04: 0 +x05: 1 +x06: 0 +x07: 1 +x08: 1 +x09: 0 +x10: 1 +x11: 0 +x12: 0 +x13: 0 +x14: 1 +x15: 0 +x16: 0 +x17: 0 +x18: 1 +x19: 0 +x20: 0 +x21: 1 +x22: 0 +x23: 0 +x24: 0 +x25: 1 +x26: 1 +x27: 1 +x28: 0 +x29: 1 +x30: 1 +x31: 1 +x32: 0 +x33: 0 +x34: 0 +x35: 1 +x36: 0 +x37: 1 +x38: 0 +x39: 0 +x40: 0 +x41: 0 +x42: 0 +x43: 0 +x44: 1 +y00: 1 +y01: 0 +y02: 1 +y03: 1 +y04: 0 +y05: 0 +y06: 1 +y07: 1 +y08: 0 +y09: 1 +y10: 1 +y11: 1 +y12: 1 +y13: 0 +y14: 1 +y15: 1 +y16: 0 +y17: 1 +y18: 0 +y19: 1 +y20: 0 +y21: 0 +y22: 0 +y23: 1 +y24: 0 +y25: 0 +y26: 0 +y27: 0 +y28: 1 +y29: 0 +y30: 0 +y31: 0 +y32: 1 +y33: 1 +y34: 0 +y35: 0 +y36: 0 +y37: 1 +y38: 1 +y39: 0 +y40: 1 +y41: 0 +y42: 0 +y43: 0 +y44: 1 + +mcb OR tbc -> hkk +y15 XOR x15 -> fns +y02 AND x02 -> jtv +qcs XOR hrs -> z19 +nvv XOR kvd -> z09 +x33 AND y33 -> nqt +hcg AND cth -> kqt +y06 AND x06 -> ksg +mqk OR vbs -> mvs +jkq XOR tsw -> z38 +y01 AND x01 -> gmn +rgg OR qgf -> vjq +jkq AND tsw -> dch +bbs XOR cbd -> z32 +y22 XOR x22 -> dtf +x36 XOR y36 -> grd +pcj XOR svn -> z04 +y06 XOR x06 -> tdv +jtn OR qcj -> tgw +gtv XOR mpd -> z35 +x25 XOR y25 -> wjb +mpg OR jtv -> jmc +rnt AND kdv -> vsk +cth XOR hcg -> z43 +x03 AND y03 -> jtm +dsh OR tcp -> bjc +kfd OR dkd -> fhf +y19 XOR x19 -> qcs +y22 AND x22 -> tcp +y28 AND x28 -> dpw +fdg XOR pnm -> z26 +x17 AND y17 -> qbc +ngv OR rvn -> ptc +dpw OR ddn -> nct +x26 XOR y26 -> pnm +qdj AND jmc -> gdr +jnw XOR qss -> z37 +x42 XOR y42 -> qwn +wwj XOR rsh -> z16 +y39 XOR x39 -> hdv +qmn XOR fvt -> z24 +tvn XOR jvq -> z07 +y38 AND x38 -> qwg +qbw XOR fns -> z15 +mkk OR mfk -> cbv +y34 AND x34 -> z34 +x44 AND y44 -> bvb +y13 XOR x13 -> whd +gdj OR vsk -> wbv +x09 AND y09 -> mqk +x00 XOR y00 -> z00 +hdv XOR pfr -> z39 +jvq AND tvn -> dkd +ndm AND tsp -> vjh +btf XOR fhf -> z08 +dtf AND wbv -> dsh +pfr AND hdv -> krw +wwb OR cpm -> jmt +wsg OR nqt -> mdh +rsk OR gmn -> vbb +cvp XOR fqv -> z25 +dqc OR qbc -> vqr +y32 XOR x32 -> bbs +x39 AND y39 -> kwg +jvj XOR mvs -> mkk +cbv XOR bmt -> z11 +bbk OR ptt -> pgg +pjm AND rvg -> ddn +grd XOR wgp -> z36 +jnw AND qss -> mvk +x04 AND y04 -> pmq +ncs OR qcb -> cth +sgv AND ntn -> rsk +y15 AND x15 -> knd +hgk XOR kvk -> z20 +y07 XOR x07 -> jvq +x27 XOR y27 -> fjb +vjq AND tmg -> kbk +mvs AND jvj -> z10 +x18 AND y18 -> rjw +y11 AND x11 -> ngv +x07 AND y07 -> kfd +tfg XOR vrb -> z44 +y24 XOR x24 -> qmn +mdh AND jmq -> cgh +pcj AND svn -> nkq +x20 XOR y20 -> kvk +x12 XOR y12 -> hnk +y44 XOR x44 -> tfg +wwj AND rsh -> qcj +x33 XOR y33 -> fms +y01 XOR x01 -> ntn +y32 AND x32 -> wwb +jmt XOR fms -> z33 +kdv XOR rnt -> z21 +bvj OR cbg -> kbc +y29 AND x29 -> rgg +y05 XOR x05 -> sgb +qmk AND rdb -> rmw +cgh OR wcb -> mpd +x12 AND y12 -> bvj +kbc XOR whd -> z13 +rmw OR hmm -> tjt +skc OR knd -> wwj +fgc OR rgp -> fvt +x41 AND y41 -> bqd +x13 AND y13 -> sbf +qcn OR wjb -> fdg +qrt AND vqr -> tvq +x23 XOR y23 -> bfq +x24 AND y24 -> jfm +jmq XOR mdh -> wcb +y23 AND x23 -> rgp +tmg XOR vjq -> z30 +x17 XOR y17 -> rps +y30 AND x30 -> dfh +y27 AND x27 -> ccs +fjb AND hkk -> gbc +x36 AND y36 -> qfv +bmt AND cbv -> rvn +x19 AND y19 -> bfp +tgw AND rps -> dqc +vqr XOR qrt -> z18 +y10 XOR x10 -> jvj +gcd XOR vbb -> z02 +pjm XOR rvg -> z28 +y11 XOR x11 -> bmt +wkt AND pfh -> kqn +gbc OR ccs -> pjm +x14 XOR y14 -> tsp +qbw AND fns -> skc +x10 AND y10 -> mfk +cbd AND bbs -> cpm +sgb AND wqq -> bbk +bfq AND bjc -> fgc +sgv XOR ntn -> z01 +y16 XOR x16 -> rsh +y30 XOR x30 -> tmg +kqt OR qws -> vrb +y41 XOR x41 -> pph +ndm XOR tsp -> qbw +x38 XOR y38 -> tsw +x14 AND y14 -> fhq +nvv AND kvd -> vbs +dkk OR tqj -> nvv +x08 XOR y08 -> btf +y35 AND x35 -> fgd +jpg XOR nct -> z29 +x02 XOR y02 -> gcd +bfp OR hws -> hgk +jpg AND nct -> qgf +qwn AND hnj -> ncs +hjt OR sbf -> ndm +y28 XOR x28 -> rvg +x31 AND y31 -> gvk +x29 XOR y29 -> jpg +x25 AND y25 -> cvp +gtv AND mpd -> tmm +tmm OR fgd -> wgp +bjc XOR bfq -> z23 +x21 XOR y21 -> rnt +x00 AND y00 -> sgv +wgp AND grd -> rrc +pfh XOR wkt -> z31 +pkq OR ksg -> tvn +y08 AND x08 -> tqj +y34 XOR x34 -> jmq +rvw OR tcc -> kdv +x26 AND y26 -> tbc +x05 AND y05 -> ptt +x43 XOR y43 -> hcg +y03 XOR x03 -> qdj +jtm OR gdr -> svn +kbk OR dfh -> wkt +tdv AND pgg -> pkq +y09 XOR x09 -> kvd +pph XOR tjt -> z41 +rjw OR tvq -> hrs +wbv XOR dtf -> z22 +krw OR kwg -> qmk +vbb AND gcd -> mpg +y42 AND x42 -> qcb +jfm OR mcr -> fqv +hgk AND kvk -> tcc +x37 AND y37 -> mrv +y20 AND x20 -> rvw +wqq XOR sgb -> z05 +y43 AND x43 -> qws +tgw XOR rps -> z17 +y04 XOR x04 -> pcj +hnk AND ptc -> cbg +pnm AND fdg -> mcb +fms AND jmt -> wsg +x35 XOR y35 -> gtv +qmk XOR rdb -> z40 +x16 AND y16 -> jtn +vjh OR fhq -> z14 +y21 AND x21 -> gdj +x18 XOR y18 -> qrt +vrb AND tfg -> bwp +kqn OR gvk -> cbd +ptc XOR hnk -> z12 +jcb OR bqd -> hnj +qmn AND fvt -> mcr +whd AND kbc -> hjt +pmq OR nkq -> wqq +cvp AND fqv -> qcn +fhf AND btf -> dkk +x40 XOR y40 -> rdb +pgg XOR tdv -> z06 +mvk OR mrv -> jkq +hkk XOR fjb -> z27 +hrs AND qcs -> hws +bwp OR bvb -> z45 +qwn XOR hnj -> z42 +x31 XOR y31 -> pfh +x40 AND y40 -> hmm +jmc XOR qdj -> z03 +x37 XOR y37 -> qss +tjt AND pph -> jcb +rrc OR qfv -> jnw +qwg OR dch -> pfr diff --git a/src/day-24.lisp b/src/day-24.lisp @@ -0,0 +1,136 @@ +(defpackage #:aoc/day-24 + (:use #:cl #:aoc/utils) + (:export #:day-24)) +(in-package #:aoc/day-24) + +(defstruct node + name + (value 0)) + +(defstruct gate + type + inputs + output) + +(defun parse-input (input) + (let ((nodes (make-hash-table :test #'equal))) + (loop for line = (read-line input) + until (= (length line) 0) + for colon = (position #\: line) + for node = (make-node :name (subseq line 0 colon) + :value (parse-integer line :start (+ colon 2))) + do (setf (gethash (node-name node) nodes) node)) + (values + (hash-table-values nodes) + (loop for line = (read-line input nil) + until (null line) + for parts = (uiop:split-string line :separator '(#\Space)) + for gate = (make-gate :type (eswitch ((nth 1 parts) :test #'string=) + ("OR" #'logior) + ("AND" #'logand) + ("XOR" #'logxor)) + :inputs (list (ensure-gethash (nth 0 parts) nodes + (make-node :name (nth 0 parts))) + (ensure-gethash (nth 2 parts) nodes + (make-node :name (nth 2 parts)))) + :output (ensure-gethash (nth 4 parts) nodes + (make-node :name (nth 4 parts)))) + collect gate) + nodes))) + +(defun ready-gates (nodes gates) + (loop for gate in gates + when (every (lambda (node) + (member node nodes)) + (gate-inputs gate)) + collect gate)) + +(defun run-gate (gate) + (setf (node-value (gate-output gate)) + (apply (gate-type gate) + (mapcar #'node-value + (gate-inputs gate))))) + +(defun prefix-nodes (nodes prefix) + (sort (loop for node in nodes + when (char= (aref (node-name node) 0) prefix) + collect node) + #'string> + :key #'node-name)) + +(defun run-all-gates (nodes gates) + (loop for ready = (ready-gates nodes gates) + until (null ready) + do (loop for gate in ready + do (run-gate gate) + (push (gate-output gate) nodes) + (setf gates (remove gate gates))) + finally (return (prefix-nodes nodes #\z)))) + +(defun nodes-result (nodes) + (loop with result = 0 + for node in nodes + do (setf result (ash result 1) + result (logior result (node-value node))) + finally (return result))) + +(defun task-1 (nodes gates) + (nodes-result (run-all-gates nodes gates))) + +(defun reset-values (nodes) + (loop for node in nodes + for f = (aref (node-name node) 0) + unless (or (char= f #\x) + (char= f #\y)) + do (setf (node-value node) 0))) + +(defun find-gate-for-output (gates output) + (find output gates + :key #'gate-output)) + +(defun swap-outputs (gates output-1 output-2) + (let ((gate-1 (find-gate-for-output gates output-1)) + (gate-2 (find-gate-for-output gates output-2))) + (psetf (gate-output gate-1) (gate-output gate-2) + (gate-output gate-2) (gate-output gate-1)))) + +(defun function-name (function) + (cond + ((eq function #'logand) "AND") + ((eq function #'logior) "OR") + ((eq function #'logxor) "XOR") + (t "?"))) + +(defun swap-all (all-nodes gates pairs) + (loop for pair in pairs + for nodes = (mapcar (rcurry #'gethash all-nodes) pair) + do (apply #'swap-outputs gates nodes))) + +(defun task-2 (nodes gates) + (swap-all nodes gates + '(("mkk" "z10") + ("qbw" "z14") + ("wcb" "z34") + ("wjb" "cvp"))) + (with-open-file (s #P"out.dot" + :direction :output + :if-exists :supersede) + (format s "digraph {~%") + (loop for gate in gates + for gate-type = (function-name (gate-type gate)) + for gate-name = (format nil "~A_~A_~A" + (node-name (first (gate-inputs gate))) + gate-type + (node-name (second (gate-inputs gate)))) + do (format s "~A[label=\"~A\"];~%" gate-name gate-type) + (format s "~A -> ~A;~%" gate-name (node-name (gate-output gate))) + (loop for input in (gate-inputs gate) + do (format s "~A -> ~A;~%" (node-name input) gate-name))) + (format s "}~%")) + "cvp,mkk,qbw,wcb,wjb,z10,z14,z34") + +(defun day-24 (input) + (multiple-value-bind (nodes gates all-nodes) + (parse-input input) + (values (task-1 nodes gates) + (task-2 all-nodes gates)))) diff --git a/t/day-24.lisp b/t/day-24.lisp @@ -0,0 +1,54 @@ +(defpackage #:aoc-test/day-24 + (:use #:cl #:lisp-unit2) + (:import-from #:aoc/day-24)) +(in-package #:aoc-test/day-24) + +(define-test test-day-24 + () + (assert= 2024 (aoc:run-day 24 "x00: 1 +x01: 0 +x02: 1 +x03: 1 +x04: 0 +y00: 1 +y01: 1 +y02: 1 +y03: 1 +y04: 1 + +ntg XOR fgs -> mjb +y02 OR x01 -> tnw +kwq OR kpj -> z05 +x00 OR x03 -> fst +tgd XOR rvg -> z01 +vdt OR tnw -> bfw +bfw AND frj -> z10 +ffh OR nrd -> bqk +y00 AND y03 -> djm +y03 OR y00 -> psh +bqk OR frj -> z08 +tnw OR fst -> frj +gnj AND tgd -> z11 +bfw XOR mjb -> z00 +x03 OR x00 -> vdt +gnj AND wpb -> z02 +x04 AND y00 -> kjc +djm OR pbm -> qhw +nrd AND vdt -> hwm +kjc AND fst -> rvg +y04 OR y02 -> fgs +y01 AND x02 -> pbm +ntg OR kjc -> kwq +psh XOR fgs -> tgd +qhw XOR tgd -> z09 +pbm OR djm -> kpj +x03 XOR y03 -> ffh +x00 XOR y04 -> ntg +bfw OR bqk -> z06 +nrd XOR fgs -> wpb +frj XOR qhw -> z04 +bqk OR frj -> z07 +y03 OR x01 -> nrd +hwm AND bqk -> z03 +tgd XOR rvg -> z12 +tnw OR pbm -> gnj")))