From e088178b3a76f1069ba6f97207912dfdc62503d9 Mon Sep 17 00:00:00 2001 From: haskal Date: Thu, 5 Dec 2019 01:21:45 -0500 Subject: [PATCH] Day 5 --- 5.rkt | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 5.rkt diff --git a/5.rkt b/5.rkt new file mode 100644 index 0000000..a680545 --- /dev/null +++ b/5.rkt @@ -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) \ No newline at end of file