Created
December 9, 2019 10:58
-
-
Save sotolf2/0b2f94d94ae38c6c10de0e5d8b5840af to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang racket | |
(define (get-input) | |
(map string->number (string-split (car (file->lines "day9.txt")) ","))) | |
(define test-code '(109 1 204 -1 1001 100 1 100 1008 100 16 101 1006 101 0 99)) | |
(define test-code2 '(1102 34915192 34915192 7 4 7 99 0)) | |
(define test-code3 '(104 1125899906842624 99)) | |
(define (code->hash code) | |
(define (step code ip hsh) | |
(if (empty? code) | |
hsh | |
(step (cdr code) (+ 1 ip) (hash-set hsh ip (car code))))) | |
(step code 0 #hash())) | |
(struct parameter (value mode) #:transparent) | |
(struct opcode (op a b c) #:transparent) | |
(struct state (output code ip base) #:transparent) | |
(define (run-code code input [feedback #f] [ip 0]) | |
(define (decode-op code ip) | |
(let* ([base (hash-ref code ip 0)] | |
[pm1 (modulo (quotient base 100) 10)] | |
[pm2 (modulo (quotient base 1000) 10)] | |
[pm3 (modulo (quotient base 10000) 10)] | |
[op (modulo base 100)]) | |
(opcode op (parameter 1 pm1) (parameter 2 pm2) (parameter 3 pm3)))) | |
(define (parameter-get parameter code ip base) | |
(cond [(= 1 (parameter-mode parameter)) (hash-ref code (+ ip (parameter-value parameter)) 0)] | |
[(= 0 (parameter-mode parameter)) (hash-ref code (hash-ref code (+ ip (parameter-value parameter)) 0) 0)] | |
[(= 2 (parameter-mode parameter)) (hash-ref code (+ base (hash-ref code (+ ip (parameter-value parameter))) 0) 0)])) | |
(define (parameter-get-address parameter code ip base) | |
(cond [(= 1 (parameter-mode parameter)) (+ ip (parameter-value parameter) 0)] | |
[(= 0 (parameter-mode parameter)) (hash-ref code (+ ip (parameter-value parameter)) 0)] | |
[(= 2 (parameter-mode parameter)) (+ base (hash-ref code (+ ip (parameter-value parameter))) 0)])) | |
(define (add code ain bin cin ip base) | |
(let ([a (parameter-get ain code ip base)] | |
[b (parameter-get bin code ip base)] | |
[c (parameter-get-address cin code ip base)]) | |
(hash-set code c (+ a b)))) | |
(define (mul code ain bin cin ip base) | |
(let ([a (parameter-get ain code ip base)] | |
[b (parameter-get bin code ip base)] | |
[c (parameter-get-address cin code ip base)]) | |
(hash-set code c (* a b)))) | |
(define (inp code ain ip input base) | |
(let ([a (parameter-get-address ain code ip base)]) | |
(hash-set code a input))) | |
(define (out code ain ip output base) | |
(let ([a (parameter-get ain code ip base)]) | |
(cons a output))) | |
(define (jit code ain bin ip base) | |
(let ([a (parameter-get ain code ip base)] | |
[b (parameter-get bin code ip base)]) | |
(if (zero? a) | |
(+ 3 ip) | |
b))) | |
(define (jif code ain bin ip base) | |
(let ([a (parameter-get ain code ip base)] | |
[b (parameter-get bin code ip base)]) | |
(if (zero? a) | |
b | |
(+ 3 ip)))) | |
(define (ilt code ain bin cin ip base) | |
(let ([a (parameter-get ain code ip base)] | |
[b (parameter-get bin code ip base)] | |
[c (parameter-get-address cin code ip base)]) | |
(if (< a b) | |
(hash-set code c 1) | |
(hash-set code c 0)))) | |
(define (ieq code ain bin cin ip base) | |
(let ([a (parameter-get ain code ip base)] | |
[b (parameter-get bin code ip base)] | |
[c (parameter-get-address cin code ip base)]) | |
(if (= a b) | |
(hash-set code c 1) | |
(hash-set code c 0)))) | |
(define (stb code ain ip base) | |
(let ([a (parameter-get ain code ip base)]) | |
(+ base a))) | |
(define (run-op code ip input output base) | |
;(displayln ip) | |
;(displayln base) | |
;(displayln input) | |
;(displayln output) | |
;(displayln code) | |
(let ([op (decode-op code ip)]) | |
(cond [(= 99 (opcode-op op)) (reverse output)] | |
[(= 1 (opcode-op op)) (run-op (add code (opcode-a op) (opcode-b op) (opcode-c op) ip base) (+ 4 ip) input output base)] | |
[(= 2 (opcode-op op)) (run-op (mul code (opcode-a op) (opcode-b op) (opcode-c op) ip base) (+ 4 ip) input output base)] | |
[(= 3 (opcode-op op)) (run-op (inp code (opcode-a op) ip (car input) base) (+ 2 ip) (cdr input) output base)] | |
[(and (= 4 (opcode-op op)) feedback) (state (car (out code (opcode-a op) ip output base)) code (+ 2 ip) base)] | |
[(= 4 (opcode-op op)) (run-op code (+ 2 ip) input (out code (opcode-a op) ip output base) base)] | |
[(= 5 (opcode-op op)) (run-op code (jit code (opcode-a op) (opcode-b op) ip base) input output base)] | |
[(= 6 (opcode-op op)) (run-op code (jif code (opcode-a op) (opcode-b op) ip base) input output base)] | |
[(= 7 (opcode-op op)) (run-op (ilt code (opcode-a op) (opcode-b op) (opcode-c op) ip base) (+ 4 ip) input output base)] | |
[(= 8 (opcode-op op)) (run-op (ieq code (opcode-a op) (opcode-b op) (opcode-c op) ip base) (+ 4 ip) input output base)] | |
[(= 9 (opcode-op op)) (run-op code (+ 2 ip) input output (stb code (opcode-a op) ip base))]))) | |
(let ([code (code->hash code)]) | |
(run-op code ip input '() 0))) | |
(define (part1) | |
(run-code (get-input) '(1))) | |
(part1) | |
(define (part2) | |
(run-code (get-input) '(2))) | |
(part2) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment