From ee4ca7279d616136c916f6b1f7bb3262b79733b4 Mon Sep 17 00:00:00 2001 From: Jonathan Chan Date: Thu, 5 Dec 2019 00:39:19 -0800 Subject: [PATCH] Day 5. --- input/05.txt | 1 + lib.rkt | 38 ++++++++++++++++++-- src/05.rkt | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 input/05.txt create mode 100644 src/05.rkt diff --git a/input/05.txt b/input/05.txt new file mode 100644 index 0000000..d5af5a5 --- /dev/null +++ b/input/05.txt @@ -0,0 +1 @@ +3,225,1,225,6,6,1100,1,238,225,104,0,1002,188,27,224,1001,224,-2241,224,4,224,102,8,223,223,1001,224,6,224,1,223,224,223,101,65,153,224,101,-108,224,224,4,224,1002,223,8,223,1001,224,1,224,1,224,223,223,1,158,191,224,101,-113,224,224,4,224,102,8,223,223,1001,224,7,224,1,223,224,223,1001,195,14,224,1001,224,-81,224,4,224,1002,223,8,223,101,3,224,224,1,224,223,223,1102,47,76,225,1102,35,69,224,101,-2415,224,224,4,224,102,8,223,223,101,2,224,224,1,224,223,223,1101,32,38,224,101,-70,224,224,4,224,102,8,223,223,101,3,224,224,1,224,223,223,1102,66,13,225,1102,43,84,225,1101,12,62,225,1102,30,35,225,2,149,101,224,101,-3102,224,224,4,224,102,8,223,223,101,4,224,224,1,223,224,223,1101,76,83,225,1102,51,51,225,1102,67,75,225,102,42,162,224,101,-1470,224,224,4,224,102,8,223,223,101,1,224,224,1,223,224,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1108,226,677,224,1002,223,2,223,1005,224,329,101,1,223,223,108,226,226,224,1002,223,2,223,1005,224,344,1001,223,1,223,1107,677,226,224,1002,223,2,223,1006,224,359,101,1,223,223,1008,226,226,224,1002,223,2,223,1005,224,374,101,1,223,223,8,226,677,224,102,2,223,223,1006,224,389,101,1,223,223,7,226,677,224,1002,223,2,223,1005,224,404,1001,223,1,223,7,226,226,224,1002,223,2,223,1005,224,419,101,1,223,223,107,226,677,224,1002,223,2,223,1005,224,434,101,1,223,223,107,226,226,224,1002,223,2,223,1005,224,449,1001,223,1,223,1107,226,677,224,102,2,223,223,1006,224,464,1001,223,1,223,1007,677,226,224,1002,223,2,223,1006,224,479,1001,223,1,223,1107,677,677,224,1002,223,2,223,1005,224,494,101,1,223,223,1108,677,226,224,102,2,223,223,1006,224,509,101,1,223,223,7,677,226,224,1002,223,2,223,1005,224,524,1001,223,1,223,1008,677,226,224,102,2,223,223,1005,224,539,1001,223,1,223,1108,226,226,224,102,2,223,223,1005,224,554,101,1,223,223,107,677,677,224,102,2,223,223,1006,224,569,1001,223,1,223,1007,226,226,224,102,2,223,223,1006,224,584,101,1,223,223,8,677,677,224,102,2,223,223,1005,224,599,1001,223,1,223,108,677,677,224,1002,223,2,223,1005,224,614,101,1,223,223,108,226,677,224,102,2,223,223,1005,224,629,101,1,223,223,8,677,226,224,102,2,223,223,1006,224,644,1001,223,1,223,1007,677,677,224,1002,223,2,223,1006,224,659,1001,223,1,223,1008,677,677,224,1002,223,2,223,1005,224,674,101,1,223,223,4,223,99,226 diff --git a/lib.rkt b/lib.rkt index 8671871..00ca38b 100644 --- a/lib.rkt +++ b/lib.rkt @@ -5,7 +5,12 @@ (provide problem-input show-solution - sum) + sum + neq? + nzero? + list-ref* + number->digits-reverse + number->digits) ;; IO helpers @@ -25,4 +30,33 @@ ;; Common helpers ;; sum : (listof number) -> number -(define (sum ns) (apply + ns)) \ No newline at end of file +(define (sum ns) (apply + ns)) + +;; neq : any -> any -> boolean +(define (neq? v1 v2) + (not (eq? v1 v2))) + +;; nzero? : number -> boolean +(define (nzero? n) + (not (zero? n))) + +;; list-ref* : (listof 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 (list-ref* lst pos failure-result) + (if (>= pos (length lst)) + 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))))) + +;; 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 diff --git a/src/05.rkt b/src/05.rkt new file mode 100644 index 0000000..6869258 --- /dev/null +++ b/src/05.rkt @@ -0,0 +1,98 @@ +#lang racket + +(require "../lib.rkt") + +;; 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 ","))) + +(define input + (string->program (car (problem-input 5)))) + +(struct instruction + (opcode mode1 mode2 mode3) + #:transparent) + +;; fetch : number -> number -> program -> program +;; If the mode is 0, the value at pointer is an address. +;; If the mode is 1, the value at pointer is immediate. +;; Return the value at that address or the immediate. +(define (fetch mode pointer program) + (if (zero? mode) + (list-ref program (list-ref program pointer)) + (list-ref program pointer))) + +;; write : number -> number -> program -> program +;; Write the value into the location at pointer. +(define (write value pointer program) + (list-set program (list-ref program pointer) value)) + +;; decode-instr : number -> instruction +;; 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. +;; Note that leading zeroes in the encoded instruction are omitted. +(define (decode-instr n) + (let* ([cs (number->digits-reverse n)] + [ops '(1 2 3 4 5 6 7 8 99)] + [op? (λ (v) (member v ops))]) + (match cs + [(list-rest (? op? op) rest) + (instruction op + (list-ref* rest 1 0) + (list-ref* rest 2 0) + (list-ref* rest 3 0))] + [(list-rest 9 9 _) + (instruction 99 0 0 0)]))) + +;; exec : number -> program -> program +(define (exec pointer program) + (let* ([instr (decode-instr (list-ref program pointer))] + [v1 (λ () (fetch (instruction-mode1 instr) (+ pointer 1) program))] + [v2 (λ () (fetch (instruction-mode2 instr) (+ pointer 2) program))] + [next-pointer + (λ (op) (match op + [(or 1 2 7 8) (+ pointer 4)] + [(or 3 4) (+ pointer 2)] + [(or 5 6) (+ pointer 3)]))] + [arith + (λ (op) (match op [1 +] [2 *]))] + [jump-if + (λ (op) (match op [5 nzero?] [6 zero?]))] + [lt-eq + (λ (op) (match op [7 <] [8 =]))]) + (match (instruction-opcode instr) + [(and op (or 1 2)) + (let* ([program (write ((arith op) (v1) (v2)) (+ pointer 3) program)]) + (exec (next-pointer op) program))] + [3 + (let* ([input (read)] + [program (write input (+ pointer 1) program)]) + (exec (next-pointer 3) program))] + [4 + (displayln (v1)) + (exec (next-pointer 4) program)] + [(and op (or 5 6)) + (let* ([pointer (if ((jump-if op) (v1)) (v2) + (next-pointer op))]) + (exec pointer program))] + [(and op (or 7 8)) + (let* ([v3 (if ((lt-eq op) (v1) (v2)) 1 0)] + [program (write v3 (+ pointer 3) program)]) + (exec (next-pointer op) program))] + [99 program]))) + +(define (execute) + (exec 0 input) + (void)) \ No newline at end of file