This commit is contained in:
xenia 2019-12-05 01:21:45 -05:00
parent 67fd4330b8
commit e088178b3a
1 changed files with 85 additions and 0 deletions

85
5.rkt Normal file
View File

@ -0,0 +1,85 @@
#lang racket
;; First some helpers
(define (op-mode opcode idx)
(match (modulo (floor (/ opcode (expt 10 (+ idx 2)))) 10)
[0 'pos]
[1 'imm]
[_ (error "invalid mode")]))
(define (op-op opcode)
(modulo opcode 100))
(define (tape-ref/mode tape pos mode)
(match mode
['pos (list-ref tape (list-ref tape pos))]
['imm (list-ref tape pos)]
[_ (error "invalid mode")]))
;; Generic abstracted opcode interpreter function
;; Calls handler for opcode-specific handling, which should call callback to continue or return to
;; exit.
(define (intcode-handle-opcode callback spec handler tape pos)
(let* ([opcode (list-ref tape pos)]
[args (for/list ([spec-item spec] [idx (in-range (length spec))])
(tape-ref/mode tape (+ pos idx 1)
(match spec-item
['in (op-mode opcode idx)]
['out 'imm])))])
(apply handler callback tape (+ pos (length spec) 1) args)))
;; Create a system to register intcode ops
(struct intcode-op [code spec handler])
(define opcode-table (make-hash))
;; Evil mutation incoming!!!!
(define (intcode-register code spec handler)
(hash-set! opcode-table code (intcode-op code spec handler)))
;; Main eval function
(define (intcode-eval tape [pos 0])
(let* ([opcode (list-ref tape pos)]
[handler-entry (hash-ref opcode-table (op-op opcode))])
(intcode-handle-opcode intcode-eval
(intcode-op-spec handler-entry)
(intcode-op-handler handler-entry)
tape pos)))
;; Now it's time to define all the operations we can do
;; Binary operations!!!
(define spec-binop '(in in out))
(define ((intcode-generic-binop op) cb tape pos lhs rhs dst)
(cb (list-set tape dst (op lhs rhs)) pos))
(intcode-register 1 spec-binop (intcode-generic-binop +))
(intcode-register 2 spec-binop (intcode-generic-binop *))
(define (bool->number b) (if b 1 0))
(intcode-register 7 spec-binop (intcode-generic-binop (compose bool->number <)))
(intcode-register 8 spec-binop (intcode-generic-binop (compose bool->number =)))
;; Exit
(define (intcode-exit cb tape pos) (void))
(intcode-register 99 '() intcode-exit)
;; I/O time
(define (intcode-input cb tape pos dst)
(cb (list-set tape dst (read)) pos))
(intcode-register 3 '(out) intcode-input)
(define (intcode-output cb tape pos src)
(displayln src)
(cb tape pos))
(intcode-register 4 '(in) intcode-output)
;; Jumps
(define ((intcode-generic-jump which) cb tape pos arg dst)
(cb tape (if (which arg) dst pos)))
(intcode-register 5 '(in in) (intcode-generic-jump (compose not zero?)))
(intcode-register 6 '(in in) (intcode-generic-jump zero?))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define input (map string->number (string-split (string-trim (file->string "input.5.txt")) ",")))
(intcode-eval input)