1 (asdf:load-system :adventofcode2020)
2 (in-package #:adventofcode2020)
3 (named-readtables:in-readtable :adventofcode2020)
5 (defun make-program (insts)
6 (let ((len (length insts))
7 (parse-inst (lambda (inst)
8 (cl-ppcre:register-groups-bind
9 (code (#'parse-integer imm))
10 ("([a-z]{3}) ([-+][0-9]+)" inst)
15 :mem (make-array len :initial-contents (mapcar parse-inst insts))
16 :vis (make-array len :element-type 'bit))))
18 (defun step-program (program)
19 (let ((ptr (getf program :ptr))
20 (mem (getf program :mem))
21 (acc (getf program :acc)))
22 (if (= ptr (length mem))
23 (setf (getf program :stop) 1)
24 (if (= 1 (bit (getf program :vis) ptr))
25 (setf (getf program :stop) 2)
26 (destructuring-bind (code imm) (aref mem ptr)
27 (cond ((string= code "nop")
28 (setf (getf program :ptr) (1+ ptr)))
31 (setf (getf program :ptr) (1+ ptr))
32 (setf (getf program :acc) (+ acc imm))))
34 (setf (getf program :ptr) (+ ptr imm))))
35 (setf (bit (getf program :vis) ptr) 1))))
38 (defun run-until-stop (program)
39 (if (getf program :stop)
40 (values (getf program :acc) (getf program :stop))
41 (run-until-stop (step-program program))))
43 (defun run-with-fix (program i)
44 (let ((fixing (aref (getf program :mem) i))
45 (fix-code (lambda (inst)
46 (destructuring-bind (code imm) inst
47 (cond ((string= code "nop") (list "jmp" imm))
48 ((string= code "jmp") (list "nop" imm)))))))
49 (setf (aref (getf program :mem) i) (funcall fix-code fixing))
50 (multiple-value-bind (acc stop) (run-until-stop program)
51 (setf (aref (getf program :mem) i) fixing)
52 (setf (getf program :stop) nil)
53 (setf (getf program :ptr) 0)
54 (setf (getf program :acc) 0)
55 (setf (getf program :vis) (make-array (length (getf program :mem)) :element-type 'bit))
58 most-negative-fixnum))))
60 (defun find-fixed-result (program)
61 (loop for i from 0 below (length (getf program :mem))
62 unless (string= "acc" (first (aref (getf program :mem) i)))
63 maximizing (run-with-fix program i)))
66 (let ((program (make-program (list-from input))))
67 (part1 (run-until-stop program))
68 (part2 (find-fixed-result program))))
73 (defvar *simple-instructions*
87 (run-until-stop (make-program *simple-instructions*)))))
92 (run-with-fix (make-program *simple-instructions*) 7))))
94 (test find-fixed-result
97 (find-fixed-result (make-program *simple-instructions*)))))