blob: 30bee822bf289a10ff1210b570d6c4fa501c18b8 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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))))
|