64 lines
2.1 KiB
Racket
64 lines
2.1 KiB
Racket
#lang plai
|
|
|
|
(require data/queue
|
|
racket/set
|
|
"../lib.rkt"
|
|
"IntCode.rkt")
|
|
|
|
(define input
|
|
(string->program (car (problem-input 23))))
|
|
|
|
(define network
|
|
(build-vector 50 (λ (n) (resume-with-input (resume-with-input (exec input) n) -1))))
|
|
|
|
(define packets
|
|
(build-vector 50 (λ (_) (make-queue))))
|
|
|
|
(define (waiting? st)
|
|
(type-case state st
|
|
[in (_) #t]
|
|
[else #f]))
|
|
|
|
(define part2
|
|
(let/cc k
|
|
(let ([prev-NATx 0]
|
|
[prev-NATy 0]
|
|
[NATx -1]
|
|
[NATy -1])
|
|
(let loop ()
|
|
(for ([i (range 0 50)])
|
|
(let ([st (vector-ref network i)]
|
|
[input (vector-ref packets i)])
|
|
(type-case state st
|
|
[in (resume)
|
|
(if (queue-empty? input)
|
|
(void)
|
|
(let* ([x (dequeue! input)]
|
|
[y (dequeue! input)]
|
|
[st (resume-with-input (resume x) y)])
|
|
(vector-set! network i st)))]
|
|
[out (j resume)
|
|
(let*-values ([(x st) (resume-with-output (resume))]
|
|
[(y st) (resume-with-output st)])
|
|
(if (= j 255)
|
|
(begin
|
|
(when (= NATy -1)
|
|
(printf "Part 1: ~a\n" y))
|
|
(set! NATx x)
|
|
(set! NATy y))
|
|
(begin
|
|
(enqueue! (vector-ref packets j) x)
|
|
(enqueue! (vector-ref packets j) y)))
|
|
(vector-set! network i st))]
|
|
[halt (_) (error "Unexpected program state.")])))
|
|
(when (and (andmap (∘ waiting? (∂ vector-ref network)) (range 0 50))
|
|
(andmap queue-empty? (vector->list packets)))
|
|
(when (= NATy prev-NATy) (k NATy))
|
|
(let ([addr0 (vector-ref packets 0)])
|
|
(set! prev-NATx NATx)
|
|
(set! prev-NATy NATy)
|
|
(enqueue! addr0 NATx)
|
|
(enqueue! addr0 NATy)))
|
|
(loop)))))
|
|
|
|
(printf "Part 2: ~a\n" part2) |