|
|
|
@ -1,16 +1,16 @@
|
|
|
|
|
#lang br
|
|
|
|
|
(require racket/file rackunit racket/generator)
|
|
|
|
|
(require racket/file rackunit)
|
|
|
|
|
|
|
|
|
|
(define (string->ints str) (map string->number (string-split str #px",\\s*")))
|
|
|
|
|
(define (string->regs str) (list->vector (string->ints str)))
|
|
|
|
|
|
|
|
|
|
(define ((binarize proc) x y) (if (proc x y) 1 0))
|
|
|
|
|
|
|
|
|
|
(define (run str . inputs)
|
|
|
|
|
(define regs (string->regs str))
|
|
|
|
|
(define (make-amp-thread program calling-thd)
|
|
|
|
|
(thread (λ ()
|
|
|
|
|
(define regs (string->regs program))
|
|
|
|
|
(define (reg-ref ptr) (vector-ref regs ptr))
|
|
|
|
|
(define (reg-set! ptr val) (vector-set! regs (reg-ref ptr) val))
|
|
|
|
|
(define ip (open-input-string (string-join (map ~a inputs) " ")))
|
|
|
|
|
(let/ec terminate
|
|
|
|
|
(let loop ([ptr 0])
|
|
|
|
|
(match-define (list opcode mode-1 mode-2 mode-3)
|
|
|
|
@ -31,9 +31,8 @@
|
|
|
|
|
(+ ptr 4)]
|
|
|
|
|
[(or 3 4) ; 2-arity: input & output
|
|
|
|
|
(match opcode
|
|
|
|
|
[3 (parameterize ([current-input-port ip])
|
|
|
|
|
(reg-set! (+ ptr 1) (read)))]
|
|
|
|
|
[4 (println (mode-1 ptr))])
|
|
|
|
|
[3 (reg-set! (+ ptr 1) (thread-receive))]
|
|
|
|
|
[4 (thread-send calling-thd (mode-1 ptr))])
|
|
|
|
|
(+ ptr 2)]
|
|
|
|
|
[(or 5 6) ; 3-arity: jump
|
|
|
|
|
(if ((match opcode
|
|
|
|
@ -42,16 +41,20 @@
|
|
|
|
|
(mode-2 ptr)
|
|
|
|
|
(+ ptr 3))]
|
|
|
|
|
[99 (terminate)]
|
|
|
|
|
[_ (error 'unknown-opcode)]))
|
|
|
|
|
(loop next-ptr))))
|
|
|
|
|
[_ (error "unknown-opcode" opcode)]))
|
|
|
|
|
(loop next-ptr))))))
|
|
|
|
|
|
|
|
|
|
(define-syntax-rule (last-output func)
|
|
|
|
|
(last (map string->number (string-split (with-output-to-string (λ () func))))))
|
|
|
|
|
(define (make-amp-threads program phases)
|
|
|
|
|
(for/list ([phase (in-list (if (string? phases) (string->ints phases) phases))])
|
|
|
|
|
(define thd (make-amp-thread program (current-thread)))
|
|
|
|
|
(thread-send thd phase)
|
|
|
|
|
thd))
|
|
|
|
|
|
|
|
|
|
(define (thruster-signal program phases)
|
|
|
|
|
(for/fold ([input 0])
|
|
|
|
|
([phase (in-list (if (string? phases) (string->ints phases) phases))])
|
|
|
|
|
(last-output (run program phase input))))
|
|
|
|
|
([amp (in-list (make-amp-threads program phases))])
|
|
|
|
|
(thread-send amp input)
|
|
|
|
|
(thread-receive)))
|
|
|
|
|
|
|
|
|
|
(check-eq? (thruster-signal "3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0" "4,3,2,1,0") 43210)
|
|
|
|
|
(check-eq? (thruster-signal "3,23,3,24,1002,24,10,24,1002,23,-1,23,
|
|
|
|
@ -59,8 +62,34 @@
|
|
|
|
|
(check-eq? (thruster-signal "3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,
|
|
|
|
|
1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0" "1,0,4,3,2") 65210)
|
|
|
|
|
|
|
|
|
|
(define amp-program (file->string "07.rktd"))
|
|
|
|
|
|
|
|
|
|
;; 1
|
|
|
|
|
(check-eq?
|
|
|
|
|
(apply max (for/list ([phases (in-permutations '(0 1 2 3 4))])
|
|
|
|
|
(thruster-signal (file->string "07.rktd") phases)))
|
|
|
|
|
(thruster-signal amp-program phases)))
|
|
|
|
|
87138)
|
|
|
|
|
|
|
|
|
|
(define (thruster-signal-cycle program phases)
|
|
|
|
|
(for/fold ([input 0])
|
|
|
|
|
([amp (in-cycle (make-amp-threads program phases))]
|
|
|
|
|
#:break (not (thread-running? amp)))
|
|
|
|
|
(thread-send amp input)
|
|
|
|
|
(thread-receive)))
|
|
|
|
|
|
|
|
|
|
(check-eq?
|
|
|
|
|
(thruster-signal-cycle "3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,
|
|
|
|
|
27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5" "9,8,7,6,5")
|
|
|
|
|
139629729)
|
|
|
|
|
|
|
|
|
|
(check-eq?
|
|
|
|
|
(thruster-signal-cycle "3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,
|
|
|
|
|
-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,
|
|
|
|
|
53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10" "9,7,8,5,6")
|
|
|
|
|
18216)
|
|
|
|
|
|
|
|
|
|
;; 2
|
|
|
|
|
(check-eq?
|
|
|
|
|
(apply max (for/list ([phases (in-permutations '(5 6 7 8 9))])
|
|
|
|
|
(thruster-signal-cycle amp-program phases)))
|
|
|
|
|
17279674)
|