Day 9; Cleanup of IntCode interpreter and solutions from past days.
This commit is contained in:
parent
e16d1abe4d
commit
28a510f3ec
|
@ -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
|
|
@ -0,0 +1,37 @@
|
||||||
|
#lang racket
|
||||||
|
|
||||||
|
(define space
|
||||||
|
(string-append
|
||||||
|
"░░░░░"
|
||||||
|
"░░░░░"
|
||||||
|
"░░░░░"
|
||||||
|
"░░░░░"
|
||||||
|
"░░░░░"
|
||||||
|
"░░░░░"))
|
||||||
|
|
||||||
|
(define A
|
||||||
|
(string-append
|
||||||
|
"░░█░░"
|
||||||
|
"░█░█░"
|
||||||
|
"█░░░█"
|
||||||
|
"█████"
|
||||||
|
"█░░░█"
|
||||||
|
"█░░░█"))
|
||||||
|
|
||||||
|
(define B
|
||||||
|
(string-append
|
||||||
|
"███░░"
|
||||||
|
"█░░█░"
|
||||||
|
"███░░"
|
||||||
|
"█░░█░"
|
||||||
|
"█░░█░"
|
||||||
|
"███░░"))
|
||||||
|
|
||||||
|
(define C
|
||||||
|
(string-append
|
||||||
|
"░░██░"
|
||||||
|
"░█░░█"
|
||||||
|
"█░░░░"
|
||||||
|
"█░░░░"
|
||||||
|
"░█░░█"
|
||||||
|
"░░██░"))
|
84
lib.rkt
84
lib.rkt
|
@ -8,12 +8,16 @@
|
||||||
sum
|
sum
|
||||||
neq?
|
neq?
|
||||||
nzero?
|
nzero?
|
||||||
|
number->digits-reverse
|
||||||
|
number->digits
|
||||||
rac
|
rac
|
||||||
list-ref*
|
list-ref*
|
||||||
number->digits-reverse
|
chunks-of
|
||||||
number->digits)
|
transpose
|
||||||
|
vector-ref*
|
||||||
|
vector-set!*)
|
||||||
|
|
||||||
;; IO helpers
|
;; IO helpers ;;
|
||||||
|
|
||||||
;; problem-input : number? -> (listof string?)
|
;; problem-input : number? -> (listof string?)
|
||||||
;; Return contents of input file input/xx.txt as lines of strings.
|
;; 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))
|
(printf "Part 1: ~a\nPart 2: ~a\n" part1 part2))
|
||||||
|
|
||||||
|
|
||||||
;; Common helpers
|
;; Number helpers ;;
|
||||||
|
|
||||||
;; sum : (listof number) -> number
|
;; sum : (listof number) -> number
|
||||||
(define (sum ns) (apply + ns))
|
(define (sum ns) (apply + ns))
|
||||||
|
@ -41,6 +45,22 @@
|
||||||
(define (nzero? n)
|
(define (nzero? n)
|
||||||
(not (zero? 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)
|
;; rac : (listof any) -> any -> (listof any)
|
||||||
;; Append element to the back of the list.
|
;; Append element to the back of the list.
|
||||||
(define (rac lst v)
|
(define (rac lst v)
|
||||||
|
@ -54,15 +74,49 @@
|
||||||
failure-result
|
failure-result
|
||||||
(list-ref lst pos)))
|
(list-ref lst pos)))
|
||||||
|
|
||||||
;; number->digits-reverse : number -> (listof number)
|
;; chunks-of : (listof any) -> nonzero? -> (listof (listof any))
|
||||||
;; Return the digits of the given number in reverse order (i.e. RTL)
|
;; Partitions a list into lists of the given size in order,
|
||||||
(define (number->digits-reverse n)
|
;; with the final list possibly being smaller
|
||||||
(if (< n 10)
|
;; e.g. '(1 2 3 4 5) 2 => '((1 2) (3 4) (5))
|
||||||
(list n)
|
(define (chunks-of lst size)
|
||||||
(cons (remainder n 10)
|
(if (< (length lst) size) lst
|
||||||
(number->digits-reverse (quotient n 10)))))
|
(cons (take lst size)
|
||||||
|
(chunks-of (drop lst size) size))))
|
||||||
|
|
||||||
;; number->digits : number -> (listof number)
|
;; transpose : (listof (listof any)) -> (listof (listof any))
|
||||||
;; Return the digits of the given number (LTR)
|
;; Turns a list of lists into a list of lists of
|
||||||
(define (number->digits n)
|
;; the first elements of the lists, ..., the nth elements
|
||||||
(reverse (number->digits-reverse n)))
|
;; 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)))
|
24
src/01.rkt
24
src/01.rkt
|
@ -2,30 +2,6 @@
|
||||||
|
|
||||||
(require "../lib.rkt")
|
(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)))
|
(define input (map string->number (problem-input 1)))
|
||||||
|
|
||||||
;; calc-fuel : number -> number
|
;; calc-fuel : number -> number
|
||||||
|
|
36
src/02.rkt
36
src/02.rkt
|
@ -1,34 +1,29 @@
|
||||||
#lang racket
|
#lang racket
|
||||||
|
|
||||||
(require "../lib.rkt")
|
(require "../lib.rkt"
|
||||||
|
"IntCode.rkt"
|
||||||
|
racket/vector)
|
||||||
|
|
||||||
(define input
|
(define input
|
||||||
(map string->number (string-split (car (problem-input 2)) ",")))
|
(string->program (car (problem-input 2))))
|
||||||
|
|
||||||
(define (input-nv nv)
|
(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)
|
(define (exec-pos0 program)
|
||||||
(let* ([opcode (list-ref program pointer)]
|
(let-values ([(program _)
|
||||||
[val1 (list-ref program (list-ref program (+ pointer 1)))]
|
(exec program)])
|
||||||
[val2 (list-ref program (list-ref program (+ pointer 2)))]
|
(vector-ref program 0)))
|
||||||
[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 part1
|
(define part1
|
||||||
(car (exec 0 (input-nv '(12 2)))))
|
(exec-pos0 (input-nv '(12 2))))
|
||||||
|
|
||||||
(define part2
|
(define part2
|
||||||
(let* ([nounverbs (cartesian-product (range 100) (range 100))]
|
(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))]
|
[nounverb (list-ref nounverbs (index-of outputs 19690720))]
|
||||||
[noun (first nounverb)]
|
[noun (first nounverb)]
|
||||||
[verb (second nounverb)])
|
[verb (second nounverb)])
|
||||||
|
@ -41,7 +36,8 @@
|
||||||
;;;; ALTERNATE SOLUTION
|
;;;; ALTERNATE SOLUTION
|
||||||
|
|
||||||
(define part2-input
|
(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)
|
(define (exec-sym pointer program)
|
||||||
(let* ([opcode (list-ref program pointer)]
|
(let* ([opcode (list-ref program pointer)]
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
(define-values (start end) (values 235741 706948))
|
(define-values (start end) (values 235741 706948))
|
||||||
|
|
||||||
(define (neq? b1 b2) (not (eq? b1 b2)))
|
|
||||||
|
|
||||||
(define (two-adjacent-digits? cs)
|
(define (two-adjacent-digits? cs)
|
||||||
(if (< (length cs) 2) #f
|
(if (< (length cs) 2) #f
|
||||||
(or (eq? (first cs)
|
(or (eq? (first cs)
|
||||||
|
|
79
src/05.rkt
79
src/05.rkt
|
@ -1,86 +1,11 @@
|
||||||
#lang racket
|
#lang racket
|
||||||
|
|
||||||
(require "../lib.rkt")
|
(require "../lib.rkt"
|
||||||
|
"IntCode.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 ",")))
|
|
||||||
|
|
||||||
(define input
|
(define input
|
||||||
(string->program (car (problem-input 5))))
|
(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
|
(define part1
|
||||||
(let-values ([(_ out) (exec input #:in '(1))])
|
(let-values ([(_ out) (exec input #:in '(1))])
|
||||||
(last out)))
|
(last out)))
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
(require data/queue
|
(require data/queue
|
||||||
"../lib.rkt"
|
"../lib.rkt"
|
||||||
"05.rkt")
|
"IntCode.rkt")
|
||||||
|
|
||||||
(define input
|
(define input
|
||||||
(string->program (car (problem-input 7))))
|
(string->program (car (problem-input 7))))
|
||||||
|
@ -69,7 +69,8 @@
|
||||||
(state program next-pointer (cdr input)))])))
|
(state program next-pointer (cdr input)))])))
|
||||||
|
|
||||||
(define (amplify-loop phase)
|
(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)])
|
[Q (make-queue)])
|
||||||
(map (curry enqueue! Q) amps)
|
(map (curry enqueue! Q) amps)
|
||||||
(let loop ([signal 0])
|
(let loop ([signal 0])
|
||||||
|
|
29
src/08.rkt
29
src/08.rkt
|
@ -8,33 +8,10 @@
|
||||||
(define width 25)
|
(define width 25)
|
||||||
(define height 6)
|
(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
|
(define layers
|
||||||
(let* ([area (* width height)]
|
(let* ([area (* width height)]
|
||||||
[chars (string->list input)])
|
[chars (string->list input)])
|
||||||
(partition-into chars area)))
|
(chunks-of chars area)))
|
||||||
|
|
||||||
(define part1
|
(define part1
|
||||||
(let* ([zeroes (map (curry count (curry eq? #\0)) layers)]
|
(let* ([zeroes (map (curry count (curry eq? #\0)) layers)]
|
||||||
|
@ -45,9 +22,9 @@
|
||||||
(* ones twos)))
|
(* ones twos)))
|
||||||
|
|
||||||
(define part2
|
(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)]
|
[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)))
|
(for-each displayln msg)))
|
||||||
|
|
||||||
(show-solution part1 #f)
|
(show-solution part1 #f)
|
|
@ -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))
|
|
@ -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))
|
Loading…
Reference in New Issue