From c0670a74b149e24ca66a71c2951bf6cc75f5a933 Mon Sep 17 00:00:00 2001 From: Jonathan Chan Date: Sun, 8 Dec 2019 23:29:20 -0800 Subject: [PATCH] Day 9; Cleanup of IntCode interpreter and solutions from past days. --- input/09.txt | 1 + letters.rkt | 37 ++++++++++++++++++++ lib.rkt | 84 +++++++++++++++++++++++++++++++++++++-------- src/01.rkt | 24 ------------- src/02.rkt | 36 +++++++++---------- src/04.rkt | 2 -- src/05.rkt | 79 ++---------------------------------------- src/07.rkt | 5 +-- src/08.rkt | 29 ++-------------- src/09.rkt | 15 ++++++++ src/IntCode.rkt | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 237 insertions(+), 166 deletions(-) create mode 100644 input/09.txt create mode 100644 letters.rkt create mode 100644 src/09.rkt create mode 100644 src/IntCode.rkt diff --git a/input/09.txt b/input/09.txt new file mode 100644 index 0000000..5d958f5 --- /dev/null +++ b/input/09.txt @@ -0,0 +1 @@ +1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,252,1,1023,1102,36,1,1008,1102,24,1,1017,1101,25,0,1013,1102,479,1,1026,1101,0,259,1022,1102,1,38,1001,1102,1,713,1024,1101,0,708,1025,1102,1,22,1006,1101,0,32,1010,1101,476,0,1027,1102,1,516,1029,1102,1,34,1009,1101,0,23,1016,1102,1,37,1011,1102,525,1,1028,1101,0,35,1004,1102,31,1,1002,1102,39,1,1019,1102,28,1,1015,1102,1,1,1021,1101,0,30,1007,1101,0,27,1014,1101,21,0,1018,1101,0,29,1005,1102,26,1,1000,1102,1,0,1020,1101,0,20,1012,1101,33,0,1003,109,13,21108,40,40,6,1005,1019,199,4,187,1106,0,203,1001,64,1,64,1002,64,2,64,109,15,1205,-7,221,4,209,1001,64,1,64,1105,1,221,1002,64,2,64,109,-25,1208,-3,26,63,1005,63,243,4,227,1001,64,1,64,1106,0,243,1002,64,2,64,109,25,2105,1,-5,1001,64,1,64,1106,0,261,4,249,1002,64,2,64,109,-4,21108,41,42,-8,1005,1016,281,1001,64,1,64,1106,0,283,4,267,1002,64,2,64,109,-6,1206,2,301,4,289,1001,64,1,64,1105,1,301,1002,64,2,64,109,-4,21102,42,1,2,1008,1016,42,63,1005,63,323,4,307,1106,0,327,1001,64,1,64,1002,64,2,64,109,-7,2108,35,1,63,1005,63,343,1105,1,349,4,333,1001,64,1,64,1002,64,2,64,109,-13,1208,7,35,63,1005,63,369,1001,64,1,64,1106,0,371,4,355,1002,64,2,64,109,24,21102,43,1,-1,1008,1017,42,63,1005,63,391,1105,1,397,4,377,1001,64,1,64,1002,64,2,64,109,-13,2101,0,-4,63,1008,63,38,63,1005,63,419,4,403,1105,1,423,1001,64,1,64,1002,64,2,64,109,21,1206,-5,435,1106,0,441,4,429,1001,64,1,64,1002,64,2,64,109,-22,21101,44,0,10,1008,1014,44,63,1005,63,463,4,447,1105,1,467,1001,64,1,64,1002,64,2,64,109,25,2106,0,-2,1106,0,485,4,473,1001,64,1,64,1002,64,2,64,109,-19,2107,37,-2,63,1005,63,501,1106,0,507,4,491,1001,64,1,64,1002,64,2,64,109,8,2106,0,10,4,513,1001,64,1,64,1105,1,525,1002,64,2,64,109,-6,21107,45,46,0,1005,1012,547,4,531,1001,64,1,64,1105,1,547,1002,64,2,64,109,-5,1202,-1,1,63,1008,63,21,63,1005,63,567,1105,1,573,4,553,1001,64,1,64,1002,64,2,64,109,2,1207,-3,21,63,1005,63,589,1105,1,595,4,579,1001,64,1,64,1002,64,2,64,109,1,1201,-8,0,63,1008,63,34,63,1005,63,619,1001,64,1,64,1106,0,621,4,601,1002,64,2,64,109,-6,2102,1,-1,63,1008,63,33,63,1005,63,643,4,627,1105,1,647,1001,64,1,64,1002,64,2,64,109,10,21101,46,0,3,1008,1017,43,63,1005,63,667,1106,0,673,4,653,1001,64,1,64,1002,64,2,64,109,-13,2102,1,8,63,1008,63,35,63,1005,63,697,1001,64,1,64,1106,0,699,4,679,1002,64,2,64,109,23,2105,1,0,4,705,1105,1,717,1001,64,1,64,1002,64,2,64,109,-1,1205,-3,729,1106,0,735,4,723,1001,64,1,64,1002,64,2,64,109,-15,2101,0,0,63,1008,63,38,63,1005,63,755,1106,0,761,4,741,1001,64,1,64,1002,64,2,64,109,-2,2107,28,-1,63,1005,63,779,4,767,1106,0,783,1001,64,1,64,1002,64,2,64,109,-2,2108,35,0,63,1005,63,801,4,789,1105,1,805,1001,64,1,64,1002,64,2,64,109,1,1201,-5,0,63,1008,63,26,63,1005,63,831,4,811,1001,64,1,64,1105,1,831,1002,64,2,64,109,-5,1207,5,30,63,1005,63,849,4,837,1106,0,853,1001,64,1,64,1002,64,2,64,109,2,1202,-2,1,63,1008,63,26,63,1005,63,879,4,859,1001,64,1,64,1105,1,879,1002,64,2,64,109,15,21107,47,46,0,1005,1017,899,1001,64,1,64,1105,1,901,4,885,4,64,99,21102,1,27,1,21101,915,0,0,1106,0,922,21201,1,66416,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,942,1,0,1105,1,922,21202,1,1,-1,21201,-2,-3,1,21102,1,957,0,1105,1,922,22201,1,-1,-2,1105,1,968,22102,1,-2,-2,109,-3,2105,1,0 diff --git a/letters.rkt b/letters.rkt new file mode 100644 index 0000000..988bdbe --- /dev/null +++ b/letters.rkt @@ -0,0 +1,37 @@ +#lang racket + +(define space + (string-append + "░░░░░" + "░░░░░" + "░░░░░" + "░░░░░" + "░░░░░" + "░░░░░")) + +(define A + (string-append + "░░█░░" + "░█░█░" + "█░░░█" + "█████" + "█░░░█" + "█░░░█")) + +(define B + (string-append + "███░░" + "█░░█░" + "███░░" + "█░░█░" + "█░░█░" + "███░░")) + +(define C + (string-append + "░░██░" + "░█░░█" + "█░░░░" + "█░░░░" + "░█░░█" + "░░██░")) \ No newline at end of file diff --git a/lib.rkt b/lib.rkt index dbfd882..25f6ebc 100644 --- a/lib.rkt +++ b/lib.rkt @@ -8,12 +8,16 @@ sum neq? nzero? + number->digits-reverse + number->digits rac list-ref* - number->digits-reverse - number->digits) + chunks-of + transpose + vector-ref* + vector-set!*) -;; IO helpers +;; IO helpers ;; ;; problem-input : number? -> (listof string?) ;; Return contents of input file input/xx.txt as lines of strings. @@ -28,7 +32,7 @@ (printf "Part 1: ~a\nPart 2: ~a\n" part1 part2)) -;; Common helpers +;; Number helpers ;; ;; sum : (listof number) -> number (define (sum ns) (apply + ns)) @@ -41,6 +45,22 @@ (define (nzero? n) (not (zero? n))) +;; number->digits-reverse : number -> (listof number) +;; Return the digits of the given number in reverse order (i.e. RTL) +(define (number->digits-reverse n) + (if (< n 10) + (list n) + (cons (remainder n 10) + (number->digits-reverse (quotient n 10))))) + +;; number->digits : number -> (listof number) +;; Return the digits of the given number (LTR) +(define (number->digits n) + (reverse (number->digits-reverse n))) + + +;; List helpers ;; + ;; rac : (listof any) -> any -> (listof any) ;; Append element to the back of the list. (define (rac lst v) @@ -54,15 +74,49 @@ failure-result (list-ref lst pos))) -;; number->digits-reverse : number -> (listof number) -;; Return the digits of the given number in reverse order (i.e. RTL) -(define (number->digits-reverse n) - (if (< n 10) - (list n) - (cons (remainder n 10) - (number->digits-reverse (quotient n 10))))) +;; chunks-of : (listof any) -> nonzero? -> (listof (listof any)) +;; Partitions a list into lists of the given size in order, +;; with the final list possibly being smaller +;; e.g. '(1 2 3 4 5) 2 => '((1 2) (3 4) (5)) +(define (chunks-of lst size) + (if (< (length lst) size) lst + (cons (take lst size) + (chunks-of (drop lst size) size)))) -;; number->digits : number -> (listof number) -;; Return the digits of the given number (LTR) -(define (number->digits n) - (reverse (number->digits-reverse n))) \ No newline at end of file +;; transpose : (listof (listof any)) -> (listof (listof any)) +;; Turns a list of lists into a list of lists of +;; the first elements of the lists, ..., the nth elements +;; where n is the length of the shortest list. +;; In short, it transposes a list of rows into a list of columns. +;; e.g. '((1 2 3 4) '((1 5 8) +;; (5 6 7) => (2 6 9) +;; (8 9 10 11 12)) (3 7 10)) +(define (transpose layers) + (if (ormap empty? layers) '() + (let ([pixels (map car layers)] + [layers (map cdr layers)]) + (cons pixels (transpose layers))))) + + +;; Vector helpers ;; + +;; vector-ref* : (vectorof any) -> number -> any -> any +;; Same as list-ref, except a default value is provided +;; if the index is beyond the length of the list. +(define (vector-ref* vec pos failure-result) + (if (>= pos (vector-length vec)) + failure-result + (vector-ref vec pos))) + +;; vector-set!* : (vectorof any) -> number -> any -> (vectorof any) +;; Set the value at given index in the vector, then return the vector +;; If the index is beyond the length of the vector, +;; a vector that can accomodate that index is returned, +;; with all the original elements and the element at the index set +(define (vector-set!* vec pos v) + (if (< pos (vector-length vec)) + (begin (vector-set! vec pos v) vec) + (let ([new-vec (make-vector (add1 pos))]) + (vector-copy! new-vec 0 vec) + (vector-set! new-vec pos v) + new-vec))) \ No newline at end of file diff --git a/src/01.rkt b/src/01.rkt index c569a37..f172714 100644 --- a/src/01.rkt +++ b/src/01.rkt @@ -2,30 +2,6 @@ (require "../lib.rkt") -#| -DAY 1: The Tyranny of the Rocket Equation (excerpt) - -PART 1: -... -Fuel required to launch a given module is based on its mass. -Specifically, to find the fuel required for a module, take its mass, -divide by three, round down, and subtract 2. -... -What is the sum of the fuel requirements for all of the modules -on your spacecraft? - -PART 2: -... -So, for each module mass, calculate its fuel and add it to the total. -Then, treat the fuel amount you just calculated as the input mass -and repeat the process, continuing until a fuel requirement is zero -or negative. -... -What is the sum of the fuel requirements for all of the modules -on your spacecraft when also taking into account the mass of the -added fuel? -|# - (define input (map string->number (problem-input 1))) ;; calc-fuel : number -> number diff --git a/src/02.rkt b/src/02.rkt index 960c499..306b91c 100644 --- a/src/02.rkt +++ b/src/02.rkt @@ -1,34 +1,29 @@ #lang racket -(require "../lib.rkt") +(require "../lib.rkt" + "IntCode.rkt" + racket/vector) (define input - (map string->number (string-split (car (problem-input 2)) ","))) + (string->program (car (problem-input 2)))) (define (input-nv nv) - (append (list (car input) (first nv) (second nv)) (cdddr input))) + (let ([input (vector-copy input)]) + (vector-set! input 1 (first nv)) + (vector-set! input 2 (second nv)) + input)) -(define (exec pointer program) - (let* ([opcode (list-ref program pointer)] - [val1 (list-ref program (list-ref program (+ pointer 1)))] - [val2 (list-ref program (list-ref program (+ pointer 2)))] - [val3 (list-ref program (+ pointer 3))] - [next-program - (cond [(= opcode 1) - (list-set program val3 (+ val1 val2))] - [(= opcode 2) - (list-set program val3 (* val1 val2))] - [else program])]) - (if (= opcode 99) - next-program - (exec (+ pointer 4) next-program)))) +(define (exec-pos0 program) + (let-values ([(program _) + (exec program)]) + (vector-ref program 0))) (define part1 - (car (exec 0 (input-nv '(12 2))))) + (exec-pos0 (input-nv '(12 2)))) (define part2 (let* ([nounverbs (cartesian-product (range 100) (range 100))] - [outputs (map (λ (nv) (car (exec 0 (input-nv nv)))) nounverbs)] + [outputs (map (λ (nv) (exec-pos0 (input-nv nv))) nounverbs)] [nounverb (list-ref nounverbs (index-of outputs 19690720))] [noun (first nounverb)] [verb (second nounverb)]) @@ -41,7 +36,8 @@ ;;;; ALTERNATE SOLUTION (define part2-input - (append (list (car input) 'noun 'verb '(+ noun verb)) (cddddr input))) + (let ([input (vector->list input)]) + (append (list (car input) 'noun 'verb '(+ noun verb)) (cddddr input)))) (define (exec-sym pointer program) (let* ([opcode (list-ref program pointer)] diff --git a/src/04.rkt b/src/04.rkt index 532e672..047f8a0 100644 --- a/src/04.rkt +++ b/src/04.rkt @@ -4,8 +4,6 @@ (define-values (start end) (values 235741 706948)) -(define (neq? b1 b2) (not (eq? b1 b2))) - (define (two-adjacent-digits? cs) (if (< (length cs) 2) #f (or (eq? (first cs) diff --git a/src/05.rkt b/src/05.rkt index 8ca8754..3ad478a 100644 --- a/src/05.rkt +++ b/src/05.rkt @@ -1,86 +1,11 @@ #lang racket -(require "../lib.rkt") - -(provide string->program - exec) - -;; string->program : string -> (listof number) -;; A program is a list of numbers, -;; which are sequences of instructions and parameters. -(define (string->program str) - (map string->number (string-split str ","))) +(require "../lib.rkt" + "IntCode.rkt") (define input (string->program (car (problem-input 5)))) -;; leave-one : (listof any) -> (listof any) -;; If the list has one or fewer elements, return the list; -;; otherwise, return the rest of the list -(define (leave-one lst) - (if (<= (length lst) 1) lst (cdr lst))) - -;; exec : program -> number -> (listof number) -> (listof number) -> program -;; An encoded instruction is anywhere from 1 to 4 digits long. -;; The last one or two digits represent the opcode, which can be: -;; - 1/2: add/multiply parameters 1 and 2 and store in parameter 3 -;; - 3: take an input and store in parameter 1 -;; - 4: output parameter 1 -;; - 5/6: if parameter 1 is non-zero/zero, jump to parameter 2 -;; - 7/8: if parameter 1 is less-than/equal-to parameter 2, -;; store 1 else store 0 in parameter 3 -;; - 99: halt -;; The next few digits to the left of the opcode (if any) represent -;; the mode of each parameter, with that of parameter i in the digit -;; i digits to the left of the opcode. -;; If the mode is 0, the value at pointer is an address. -;; If the mode is 1, the value at pointer is immediate. -;; Note that leading zeroes in the encoded instruction are omitted. -(define (exec program #:ptr [pointer 0] #:in [input '()] #:out [output '()]) - (let* ([instruction (list-ref program pointer)] - [opcode (remainder instruction 100)] - [mode1 (remainder (quotient instruction 100) 10)] - [mode2 (remainder (quotient instruction 1000) 10)] - [mode3 (remainder (quotient instruction 10000) 10)] - ;; l* : call to get write location from program - [l1 (λ () (if (zero? mode1) (list-ref program (+ pointer 1)) (+ pointer 1)))] - [l2 (λ () (if (zero? mode2) (list-ref program (+ pointer 2)) (+ pointer 2)))] - [l3 (λ () (if (zero? mode3) (list-ref program (+ pointer 3)) (+ pointer 3)))] - ;; v* : call to read values from program - [v1 (λ () (list-ref program (l1)))] - [v2 (λ () (list-ref program (l2)))] - [v3 (λ () (list-ref program (l3)))] - [next-pointer - (match opcode - [(or 1 2 7 8) (+ pointer 4)] - [(or 3 4) (+ pointer 2)] - [(or 5 6) (+ pointer 3)] - [99 (+ pointer 1)])]) - (match opcode - [(or 1 2) - (let* ([arith (match opcode [1 +] [2 *])] - [value (arith (v1) (v2))] - [program (list-set program (l3) value)]) - (exec program #:ptr next-pointer #:in input #:out output))] - [3 - (let* ([value (car input)] - [input (cdr input)] - [program (list-set program (l1) value)]) - (exec program #:ptr next-pointer #:in input #:out output))] - [4 - (let* ([output (append output `(,(v1)))]) - (exec program #:ptr next-pointer #:in input #:out output))] - [(or 5 6) - (let* ([jump-if (match opcode [5 nzero?] [6 zero?])] - [next-pointer (if (jump-if (v1)) (v2) next-pointer)]) - (exec program #:ptr next-pointer #:in input #:out output))] - [(or 7 8) - (let* ([lt-eq (match opcode [7 <] [8 =])] - [value (if (lt-eq (v1) (v2)) 1 0)] - [program (list-set program (l3) value)]) - (exec program #:ptr next-pointer #:in input #:out output))] - [99 (values program output)]))) - (define part1 (let-values ([(_ out) (exec input #:in '(1))]) (last out))) diff --git a/src/07.rkt b/src/07.rkt index 33d1cf2..e759a99 100644 --- a/src/07.rkt +++ b/src/07.rkt @@ -2,7 +2,7 @@ (require data/queue "../lib.rkt" - "05.rkt") + "IntCode.rkt") (define input (string->program (car (problem-input 7)))) @@ -69,7 +69,8 @@ (state program next-pointer (cdr input)))]))) (define (amplify-loop phase) - (let* ([amps (map (compose (curry state input 0) list) phase)] + (let* ([input (vector->list input)] + [amps (map (compose (curry state input 0) list) phase)] [Q (make-queue)]) (map (curry enqueue! Q) amps) (let loop ([signal 0]) diff --git a/src/08.rkt b/src/08.rkt index ae70111..40f1a0a 100644 --- a/src/08.rkt +++ b/src/08.rkt @@ -8,33 +8,10 @@ (define width 25) (define height 6) -;; partition-into : (listof any) -> nonzero? -> (listof (listof any)) -;; Partitions a list into lists of the given size in order, -;; with the final list possibly being smaller -;; e.g. '(1 2 3 4 5) 2 => '((1 2) (3 4) (5)) -(define (partition-into lst size) - (if (< (length lst) size) lst - (cons (take lst size) - (partition-into (drop lst size) size)))) - -;; pivot : (listof (listof any)) -> (listof (listof any)) -;; Turns a list of lists into a list of lists of -;; the first elements of the lists, ..., the nth elements -;; where n is the length of the shortest list. -;; In short, it pivots a list of rows into a list of columns. -;; e.g. '((1 2 3 4) '((1 5 8) -;; (5 6 7) => (2 6 9) -;; (8 9 10 11 12)) (3 7 10)) -(define (pivot layers) - (if (ormap empty? layers) '() - (let ([pixels (map car layers)] - [layers (map cdr layers)]) - (cons pixels (pivot layers))))) - (define layers (let* ([area (* width height)] [chars (string->list input)]) - (partition-into chars area))) + (chunks-of chars area))) (define part1 (let* ([zeroes (map (curry count (curry eq? #\0)) layers)] @@ -45,9 +22,9 @@ (* ones twos))) (define part2 - (let* ([image (map (curry findf (curry neq? #\2)) (pivot layers))] + (let* ([image (map (curry findf (curry neq? #\2)) (transpose layers))] [image* (map (λ (pixel) (if (eq? pixel #\1) #\█ #\ )) image)] - [msg (map list->string (partition-into image* width))]) + [msg (map list->string (chunks-of image* width))]) (for-each displayln msg))) (show-solution part1 #f) \ No newline at end of file diff --git a/src/09.rkt b/src/09.rkt new file mode 100644 index 0000000..648f13e --- /dev/null +++ b/src/09.rkt @@ -0,0 +1,15 @@ +#lang racket + +(require "../lib.rkt" + "IntCode.rkt") + +(define input + (string->program (car (problem-input 9)))) + +(define-values (_ part1) + (exec input #:in '(1))) + +(define-values (__ part2) + (exec input #:in '(2))) + +(show-solution (car part1) (car part2)) \ No newline at end of file diff --git a/src/IntCode.rkt b/src/IntCode.rkt new file mode 100644 index 0000000..95d3a09 --- /dev/null +++ b/src/IntCode.rkt @@ -0,0 +1,91 @@ +#lang racket + +(require racket/vector + "../lib.rkt") + +(provide string->program + exec) + +(define (vector-ref** vec pos) + (vector-ref* vec pos 0)) + +;; string->program : string -> (listof number) +;; A program is a list of numbers, +;; which are sequences of instructions and parameters. +(define (string->program str) + (list->vector (map string->number (string-split str ",")))) + +;; exec* : program -> number -> number -> (listof number) -> (listof number) -> program +;; An encoded instruction is anywhere from 1 to 4 digits long. +;; The last one or two digits represent the opcode, which can be: +;; - 1/2: add/multiply parameters 1 and 2 and store in parameter 3 +;; - 3: take an input and store in parameter 1 +;; - 4: output parameter 1 +;; - 5/6: if parameter 1 is non-zero/zero, jump to parameter 2 +;; - 7/8: if parameter 1 is less-than/equal-to parameter 2, +;; store 1 else store 0 in parameter 3 +;; - 9: add parameter 1 to relative base +;; - 99: halt +;; The next few digits to the left of the opcode (if any) represent +;; the mode of each parameter, with that of parameter i in the digit +;; i digits to the left of the opcode. +;; If the mode is 0, the value at pointer is an address. +;; If the mode is 1, the value at pointer is immediate. +;; If the mode is 2, the value at pointer is an address to be offset by base. +;; Note that leading zeroes in the encoded instruction are omitted. +(define (exec* program #:ptr [pointer 0] #:base [base 0] #:in [input '()] #:out [output '()]) + (define instruction (vector-ref** program pointer)) + (define opcode (remainder instruction 100)) + (define next-pointer + (match opcode + [(or 1 2 7 8) (+ pointer 4)] + [(or 3 4 9) (+ pointer 2)] + [(or 5 6) (+ pointer 3)] + [99 (+ pointer 1)])) + (define (get-location index mode) + (match mode + [0 (vector-ref** program (+ pointer index))] + [1 (+ pointer index)] + [2 (+ (vector-ref** program (+ pointer index)) base)])) + (let* ([mode1 (remainder (quotient instruction 100) 10)] + [mode2 (remainder (quotient instruction 1000) 10)] + [mode3 (remainder (quotient instruction 10000) 10)] + ;; l* : call to get write location from program + [l1 (λ () (get-location 1 mode1))] + [l2 (λ () (get-location 2 mode2))] + [l3 (λ () (get-location 3 mode3))] + ;; v* : call to read values from program + [v1 (λ () (vector-ref** program (l1)))] + [v2 (λ () (vector-ref** program (l2)))] + [v3 (λ () (vector-ref** program (l3)))]) + (match opcode + [(or 1 2) + (let* ([arith (match opcode [1 +] [2 *])] + [value (arith (v1) (v2))] + [program (vector-set!* program (l3) value)]) + (exec* program #:ptr next-pointer #:base base #:in input #:out output))] + [3 + (let* ([value (car input)] + [input (cdr input)] + [program (vector-set!* program (l1) value)]) + (exec* program #:ptr next-pointer #:base base #:in input #:out output))] + [4 + (let* ([output (append output `(,(v1)))]) + (exec* program #:ptr next-pointer #:base base #:in input #:out output))] + [(or 5 6) + (let* ([jump-if (match opcode [5 nzero?] [6 zero?])] + [next-pointer (if (jump-if (v1)) (v2) next-pointer)]) + (exec* program #:ptr next-pointer #:base base #:in input #:out output))] + [(or 7 8) + (let* ([lt-eq (match opcode [7 <] [8 =])] + [value (if (lt-eq (v1) (v2)) 1 0)] + [program (vector-set!* program (l3) value)]) + (exec* program #:ptr next-pointer #:base base #:in input #:out output))] + [9 + (let ([base (+ base (v1))]) + (exec* program #:ptr next-pointer #:base base #:in input #:out output))] + [99 (values program output)]))) + +;; Just so we always run the program on a fresh copy +(define (exec program #:ptr [pointer 0] #:base [base 0] #:in [input '()] #:out [output '()]) + (exec* (vector-copy program) #:ptr pointer #:base base #:in input #:out output)) \ No newline at end of file