2019/src/07.rkt

88 lines
3.5 KiB
Racket
Raw Normal View History

#lang racket
(require "../lib.rkt"
"05.rkt")
(define input
(string->program (car (problem-input 7))))
(define (amplify phase)
(let*-values ([(_ outA) (exec input #:in (list (first phase) 0))]
[(_ outB) (exec input #:in (list (second phase) (car outA)))]
[(_ outC) (exec input #:in (list (third phase) (car outB)))]
[(_ outD) (exec input #:in (list (fourth phase) (car outC)))]
[(_ outE) (exec input #:in (list (fifth phase) (car outD)))])
(car outE)))
(define part1
(let ([phases (permutations '(0 1 2 3 4))])
(apply max (append (map amplify phases)))))
;; The IntCode interpreter from Day 5, except it uses threads
(define (exec-pipe program #:ptr [pointer 0] #:thr thread)
(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-pipe program #:ptr next-pointer #:thr thread))]
[3
(let* ([value (thread-receive)]
[program (list-set program (l1) value)])
(exec-pipe program #:ptr next-pointer #:thr thread))]
[4
(thread-send thread (v1))
(exec-pipe program #:ptr next-pointer #:thr thread)]
[(or 5 6)
(let* ([jump-if (match opcode [5 nzero?] [6 zero?])]
[next-pointer (if (jump-if (v1)) (v2) next-pointer)])
(exec-pipe program #:ptr next-pointer #:thr thread))]
[(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-pipe program #:ptr next-pointer #:thr thread))]
[99
(thread-send thread (values program (thread-receive)))])))
(define (amplify-loop phase)
(let* ([threadE (thread (exec-pipe input #:thr (current-thread)))]
[threadD (thread (exec-pipe input #:thr threadE))]
[threadC (thread (exec-pipe input #:thr threadD))]
[threadB (thread (exec-pipe input #:thr threadC))]
[threadA (thread (exec-pipe input #:thr threadB))])
(thread-send threadE (fifth phase))
(thread-send threadD (fourth phase))
(thread-send threadC (third phase))
(thread-send threadB (second phase))
(thread-send threadA (first phase))
(thread-send threadA 0)
(let loop ()
(let ([msg (thread-receive)])
(if (number? msg)
(begin
(thread-send threadA msg)
(loop))
(let-values ([(_ output) msg])
output))))))
(show-solution part1 #f)