day 8 impl 3: the program analysis solution

This commit is contained in:
xenia 2020-12-08 03:18:07 -05:00
parent f032b43a80
commit e679ae62ec
1 changed files with 33 additions and 11 deletions

44
8.rkt
View File

@ -26,17 +26,39 @@
(cdr (execute-program input))) (cdr (execute-program input)))
(define (part2 input) (define (part2 input)
(let/ec exit (define target-pc (vector-length input))
(for ([ins (in-vector input)] [i (in-naturals)] ;; create naive CFG (as list of edges)
#:unless (string=? "acc" (insn-type ins))) (define model/list
(define new-insn (for/list ([i (in-naturals)] [ins (in-vector input)])
(insn (match (insn-type ins) ["jmp" "nop"] ["nop" "jmp"]) (match-define (insn type arg) ins)
(insn-arg ins))) (match type
(define new-prg (vector-copy input)) [(or "nop" "acc") (list i (add1 i))]
(vector-set! new-prg i new-insn) ["jmp" (list i (+ i arg))])))
(match (execute-program new-prg) ;; detect connected components of unweighted CFG
[(cons 'loop _) (void)] (define ccs (map list->set (cc (undirected-graph model/list))))
[(cons 'done acc) (exit acc)])))) ;; find which components we need to connect
(define to-cc (for/first ([cc (in-list ccs)] #:when (set-member? cc target-pc)) cc))
;; execute the program, but bail as soon as there's a way to to-cc
(define (execute/graph G [v 0] [acc 0] [changed? #f])
(cond
;; done!
[(= target-pc v) acc]
;; not done, yet....
[else
;; fetch instruction
(match-define (insn type arg) (vector-ref input v))
;; determine the "alternate target" if this instruction were mutated
(define alt-target (match type
["nop" (+ v arg)]
["jmp" (add1 v)]
["acc" #f]))
;; calculate new accumulator
(define new-acc (if (string=? type "acc") (+ acc arg) acc))
;; if we haven't mutated an instruction yet, and alt-target goes into to-cc, use it
(if (and (not changed?) alt-target (set-member? to-cc alt-target))
(execute/graph G alt-target new-acc #t)
(execute/graph G (first (get-neighbors G v)) new-acc changed?))]))
(execute/graph (directed-graph model/list)))
(module+ main (module+ main
(define input (define input