From 7ebcc21e127c15d244fe0fc6b5d535fd2d64be03 Mon Sep 17 00:00:00 2001 From: Adrian Braemer <11058200+NobodysHero@users.noreply.github.com> Date: Wed, 19 Dec 2018 17:34:38 +0100 Subject: [PATCH] Day 19 Added solution for day 19. Adapted day16 a bit on the way. --- advent-of-code-2018.asd | 4 ++- day16.lisp | 17 ++++++++--- day19.lisp | 63 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 day19.lisp diff --git a/advent-of-code-2018.asd b/advent-of-code-2018.asd index b1cb76a..9cb91ff 100644 --- a/advent-of-code-2018.asd +++ b/advent-of-code-2018.asd @@ -24,4 +24,6 @@ (:file "day13") (:file "day14") (:file "day16") - (:file "day17"))) + (:file "day17") + (:file "day18") + (:file "day19"))) diff --git a/day16.lisp b/day16.lisp index deebcf1..5eb41b5 100644 --- a/day16.lisp +++ b/day16.lisp @@ -2,20 +2,28 @@ (in-package :advent-of-code-2018) +(defun day16-make-test-case (line1 line2 line3) + (let ((before (extract-integers line1)) + (instruction (extract-integers line2)) + (after (extract-integers line3))) + (list (make-array (length before) :initial-contents before) + instruction + (make-array (length after) :initial-contents after)))) + (defun day16-parse-input () (with-open-file (in (puzzlepath "input16.txt")) (loop :for line := (read-line in nil) :while line :unless (= 0 (length line)) :when (char= #\B (char line 0)) - :collect (mapcar #'extract-integers (list line (read-line in) (read-line in))) :into test-cases + :collect (day16-make-test-case line (read-line in) (read-line in)) :into test-cases :else :collect (extract-integers line) :into test-prog :finally (return (list test-cases test-prog))))) (defun day16-execute! (register command) (destructuring-bind (cmd inp1 inp2 out) command (macrolet ((reg (x) - `(nth ,x register))) + `(aref register ,x))) (setf (reg out) (case cmd (addr (+ (reg inp1) (reg inp2))) @@ -65,7 +73,8 @@ :count (<= 3 (length (day16-test-case case))) :into count :finally (format t "There are ~a test cases with 3 or more possible instructions.~%" count)) (loop :with id->opcode := (day16-construct-opcode-ids cases) - :with registers := (list 0 0 0 0) + :with registers := #(0 0 0 0) :for (id . args) :in prog :do (setf registers (day16-execute! registers (cons (aref id->opcode id) args))) - :finally (format t "After executing the test program the value in register 0 is ~a.~%" (first registers))))) + :finally (format t "After executing the test program the value in register 0 is ~a.~%" + (aref registers 0))))) diff --git a/day19.lisp b/day19.lisp new file mode 100644 index 0000000..9de9d51 --- /dev/null +++ b/day19.lisp @@ -0,0 +1,63 @@ +;;;; day19.lisp + +(in-package :advent-of-code-2018) + +(defstruct (program-state (:conc-name pstate-)) + instructions + (ip 0) + (ip-binding nil) + (registers (make-array 6 :initial-element 0 :element-type 'integer))) + +(defun day19-parse-input (&optional (file (puzzlepath "input19.txt"))) + (loop-line-by-line file + :when (char= #\# (char line 0)) :collect (list 'ip (parse-integer line :start 4)) + :else :collect (cons (read-from-string line) (extract-integers line)))) + +(defun day19-initialize-program (instruction-list) + (make-program-state :instructions (make-array (1- (length instruction-list)) + :initial-contents (rest instruction-list)) + :ip-binding (second (first instruction-list)))) + +(defun day19-execute! (program-state) + (with-accessors ((instr pstate-instructions) + (ip pstate-ip) + (ip-binding pstate-ip-binding) + (registers pstate-registers)) + program-state + (when ip-binding + (setf (aref registers ip-binding) ip)) + ;(format t "before: ~a~%" registers) + (let ((command (aref instr ip))) + (if (eq 'ip (first command)) + (setf ip-binding (second command)) + (day16-execute! registers command)) + ; (format t "command: ~a~%~%" command) + ) + (when ip-binding + (setf ip (aref registers ip-binding))) + (incf ip) + (< -1 ip (length instr)))) + +;;; runs FOREVER +(defun day19-brute-force () + (loop :with prog := (day19-initialize-program (day19-parse-input)) + :count t :into loops + :while (day19-execute! prog) + :finally (format t "The first background process exits with the value ~a in the zeroth register.~%" + (aref (pstate-registers prog) 0))) + (let ((prog (day19-initialize-program (day19-parse-input)))) + (setf (aref (pstate-registers prog) 0) 1) + (loop :while (day19-execute! prog) + :finally + (format t "The second background process exits with the value ~a in the zeroth register.~%" + (aref (pstate-registers prog) 0))))) + +(defun day19-analytic (input) + (loop :for a :from 1 :upto (ceiling (sqrt input)) + :when (= 0 (mod input a)) :sum (+ a (/ input a)))) + +(defun day19 () + (format t "The first background process exits with the value ~a in the zeroth register.~%" + (day19-analytic 931)) + (format t "The second background process exits with the value ~a in the zeroth register.~%" + (day19-analytic 10551331)))