Skip to content

Instantly share code, notes, and snippets.

@death
Created December 8, 2020 08:09
Show Gist options
  • Select an option

  • Save death/45cb64fc59a0b140eafcc55f89a290f7 to your computer and use it in GitHub Desktop.

Select an option

Save death/45cb64fc59a0b140eafcc55f89a290f7 to your computer and use it in GitHub Desktop.
aoc2020 day8
;;;; +----------------------------------------------------------------+
;;;; | Advent of Code 2020 |
;;;; +----------------------------------------------------------------+
(defpackage #:snippets/aoc2020/day8
(:use #:cl)
(:import-from
#:split-sequence
#:split-sequence)
(:import-from
#:alexandria
#:make-keyword
#:destructuring-ecase)
(:export
#:day8))
(in-package #:snippets/aoc2020/day8)
(defun parse (input)
(map 'vector #'parse-instruction input))
(defun parse-instruction (string)
(destructuring-bind (operation argument)
(split-sequence #\Space string)
(list (make-keyword (string-upcase operation))
(parse-integer argument))))
(defun run (program)
(let ((pc 0)
(accumulator 0)
(executed (make-array (length program)
:element-type 'bit
:initial-element 0)))
(loop
(cond ((>= pc (length program))
(return-from run (values accumulator :finish)))
((= 1 (aref executed pc))
(return-from run (values accumulator :loop))))
(setf (aref executed pc) 1)
(destructuring-ecase (aref program pc)
((:acc increment)
(incf accumulator increment)
(incf pc))
((:nop dummy)
(declare (ignore dummy))
(incf pc))
((:jmp offset)
(incf pc offset))))))
(defun next-patch-position (program &optional (start 0))
(position-if (lambda (instruction)
(member (car instruction) '(:nop :jmp)))
program
:start start))
(defun patch (program position)
(symbol-macrolet ((instruction (aref program position)))
(setf instruction
(cons (ecase (car instruction)
(:nop :jmp)
(:jmp :nop))
(cdr instruction)))))
(defun fix (program)
(do ((position (next-patch-position program)
(next-patch-position program (1+ position))))
((null position)
(error "Can't fix program ~S." program))
(patch program position)
(multiple-value-bind (accumulator status)
(run program)
(ecase status
(:finish
(return-from fix accumulator))
(:loop
(patch program position))))))
(defun day8 (input)
(let ((program (parse input)))
(list (run program)
(fix program))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment