2019-12-02 09:25:42 +00:00
|
|
|
#lang racket
|
|
|
|
|
2019-12-09 21:09:16 +00:00
|
|
|
(require racket/vector
|
|
|
|
"../lib.rkt"
|
|
|
|
"IntCode.rkt")
|
2019-12-02 09:25:42 +00:00
|
|
|
|
|
|
|
(define input
|
2019-12-09 07:29:20 +00:00
|
|
|
(string->program (car (problem-input 2))))
|
2019-12-02 09:25:42 +00:00
|
|
|
|
|
|
|
(define (input-nv nv)
|
2019-12-09 07:29:20 +00:00
|
|
|
(let ([input (vector-copy input)])
|
|
|
|
(vector-set! input 1 (first nv))
|
|
|
|
(vector-set! input 2 (second nv))
|
|
|
|
input))
|
2019-12-02 09:25:42 +00:00
|
|
|
|
2019-12-09 07:29:20 +00:00
|
|
|
(define (exec-pos0 program)
|
2019-12-09 21:09:16 +00:00
|
|
|
(let ([program (halt-with-program (exec program))])
|
2019-12-09 07:29:20 +00:00
|
|
|
(vector-ref program 0)))
|
2019-12-02 09:25:42 +00:00
|
|
|
|
|
|
|
(define part1
|
2019-12-09 07:29:20 +00:00
|
|
|
(exec-pos0 (input-nv '(12 2))))
|
2019-12-02 09:25:42 +00:00
|
|
|
|
|
|
|
(define part2
|
|
|
|
(let* ([nounverbs (cartesian-product (range 100) (range 100))]
|
2019-12-09 07:29:20 +00:00
|
|
|
[outputs (map (λ (nv) (exec-pos0 (input-nv nv))) nounverbs)]
|
2019-12-02 09:25:42 +00:00
|
|
|
[nounverb (list-ref nounverbs (index-of outputs 19690720))]
|
|
|
|
[noun (first nounverb)]
|
|
|
|
[verb (second nounverb)])
|
|
|
|
(+ (* 100 noun) verb)))
|
|
|
|
|
|
|
|
(show-solution part1 part2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;; ALTERNATE SOLUTION
|
|
|
|
|
|
|
|
(define part2-input
|
2019-12-09 07:29:20 +00:00
|
|
|
(let ([input (vector->list input)])
|
|
|
|
(append (list (car input) 'noun 'verb '(+ noun verb)) (cddddr input))))
|
2019-12-02 09:25:42 +00:00
|
|
|
|
|
|
|
(define (exec-sym 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-sym (+ pointer 4) next-program))))
|
|
|
|
|
|
|
|
(define part2-partial
|
|
|
|
(car (exec-sym 4 part2-input)))
|
|
|
|
|
|
|
|
(define (simplify expr)
|
|
|
|
(match expr
|
|
|
|
; (op n1 n2 e) -> (simplify (op (n1 `op` n2) (simplify e)))
|
|
|
|
[(or `(,op (,op ,(? number? n1) ,e) ,(? number? n2))
|
|
|
|
`(,op (,op ,e ,(? number? n1)) ,(? number? n2))
|
|
|
|
`(,op ,(? number? n1) (,op ,(? number? n2) ,e))
|
|
|
|
`(,op ,(? number? n1) (,op ,e ,(? number? n2))))
|
|
|
|
(let ([opfun (match op ['+ +] ['* *])])
|
|
|
|
(simplify `(,op ,(opfun n1 n2) ,(simplify e))))]
|
|
|
|
|
|
|
|
; (op e1 e2 s) -> (op (simplify (op e1 e2)) s)
|
|
|
|
[(or `(,op (,op ,e1 ,(? symbol? s)) ,e2)
|
|
|
|
`(,op (,op ,(? symbol? s) ,e1) ,e2)
|
|
|
|
`(,op ,e1 (,op ,e2 ,(? symbol? s)))
|
|
|
|
`(,op ,e1 (,op ,(? symbol? s) ,e2)))
|
|
|
|
`(,op ,(simplify `(,op ,e1 ,e2)) ,s)]
|
|
|
|
|
|
|
|
; (* (+ n1 e) n2) -> (simplify (+ (n1 * n2) (simplify (* n1 e))))
|
|
|
|
[(or `(* (+ ,(? number? n2) ,e) ,(? number? n1))
|
|
|
|
`(* (+ ,e ,(? number? n2)) ,(? number? n1))
|
|
|
|
`(* ,(? number? n1) (+ ,(? number? n2) ,e))
|
|
|
|
`(* ,(? number? n1) (+ ,e ,(? number? n2))))
|
|
|
|
(simplify `(+ ,(* n1 n2) ,(simplify `(* ,n1 ,e))))]
|
|
|
|
|
|
|
|
[`(* ,(? number? n1) ,(? number? n2)) (* n1 n2)]
|
|
|
|
[`(+ ,(? number? n1) ,(? number? n2)) (+ n1 n2)]
|
|
|
|
[`(+ ,l ,r) `(+ ,(simplify l) ,(simplify r))]
|
|
|
|
[`(* ,l ,r) `(* ,(simplify l) ,(simplify r))]
|
|
|
|
[(? number? n) n]
|
|
|
|
[(? symbol? s) s]))
|
|
|
|
|
|
|
|
; (+ (+ 520625 (* 270000 noun)) verb) = 19690720
|
|
|
|
(define part2-alt
|
|
|
|
(let ([simplified (simplify part2-partial)])
|
|
|
|
(match simplified
|
|
|
|
[`(+ (+ ,n1 (* ,n2 noun)) verb)
|
|
|
|
(let* ([dividend (- 19690720 n1)]
|
|
|
|
[modulus n2]
|
|
|
|
[noun (quotient dividend modulus)]
|
|
|
|
[verb (remainder dividend modulus)])
|
|
|
|
(+ (* 100 noun) verb))])))
|