blob: 31ae24fa460ebdb3f8b06558c0b79b418f5feebc (
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
|
(defpackage #:machine
(:use :cl)
(:export :run))
(in-package #:machine)
;;; Interpreter
(defconstant +op-adv+ 0)
(defconstant +op-bxl+ 1)
(defconstant +op-bst+ 2)
(defconstant +op-jnz+ 3)
(defconstant +op-bxc+ 4)
(defconstant +op-out+ 5)
(defconstant +op-bdv+ 6)
(defconstant +op-cdv+ 7)
(defun run (program A B C)
(let ((ip 0)
output)
(flet ((fetch-oprand (oprand)
(case oprand
(4 A) (5 B) (6 C)
(otherwise oprand)))
(xdv (oprand)
(floor A (ash 2 (1- oprand)))))
(loop while (< ip (length program)) do
(let* ((opcode (aref program ip))
(oprand-lit (aref program (1+ ip)))
(oprand (fetch-oprand oprand-lit)))
(ecase opcode
(#.+op-bxl+
(setq B (logxor B oprand-lit)))
(#.+op-bst+
(setq B (logand oprand #b111)))
(#.+op-jnz+
(unless (zerop A)
(setq ip (- oprand-lit 2))))
(#.+op-bxc+
(setq B (logxor B C)))
(#.+op-out+
(push (logand oprand #b111) output))
(#.+op-adv+ (setq A (xdv oprand)))
(#.+op-bdv+ (setq B (xdv oprand)))
(#.+op-cdv+ (setq C (xdv oprand))))
(incf ip 2))))
(nreverse output)))
|