diff options
Diffstat (limited to '2019/interpreter.lisp')
-rw-r--r-- | 2019/interpreter.lisp | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/2019/interpreter.lisp b/2019/interpreter.lisp new file mode 100644 index 0000000..30bee82 --- /dev/null +++ b/2019/interpreter.lisp @@ -0,0 +1,56 @@ +(defpackage #:intcode + (:use :cl) + (:export :run :parse)) + +(in-package #:intcode) + +;;; Interpreter + +(defun run (ram) + (let ((ip 0)) + (loop + (let ((opcode (aref ram ip)) + (arg-1 (try-aref ram (+ ip 1))) + (arg-2 (try-aref ram (+ ip 2))) + (arg-3 (try-aref ram (+ ip 3)))) + (case opcode + (1 + (setf (aref ram arg-3) + (+ (aref ram arg-1) + (aref ram arg-2)))) + (2 + (setf (aref ram arg-3) + (* (aref ram arg-1) + (aref ram arg-2)))) + (99 + (return-from run)) + (otherwise + (error (format nil "Invalid opcode ā~dā" opcode))))) + (incf ip 4)))) + +;;; Input Parsing + +(defun parse (filename) + (with-open-file (stream filename) + (let ((contents (make-string (file-length stream)))) + (read-sequence contents stream) + (extract-numbers-from-string contents)))) + +(defun extract-numbers-from-string (string) + (loop for comma-pos = (position-if #'commap string) + collect (parse-integer (subseq string 0 comma-pos)) into numbers + unless comma-pos + return (coerce numbers 'vector) + do (setq string (subseq string (1+ comma-pos))))) + +;;; Helper Functions + +(defun commap (char) + (char= char #\,)) + +(defun try-aref (array &rest subscripts) + (loop for i in subscripts + for j in (array-dimensions array) + unless (< -1 i j) + return nil + finally (return (apply #'aref array subscripts))))
\ No newline at end of file |