day 8 impl 3: the program analysis solution
This commit is contained in:
parent
f032b43a80
commit
e679ae62ec
44
8.rkt
44
8.rkt
|
@ -26,17 +26,39 @@
|
|||
(cdr (execute-program input)))
|
||||
|
||||
(define (part2 input)
|
||||
(let/ec exit
|
||||
(for ([ins (in-vector input)] [i (in-naturals)]
|
||||
#:unless (string=? "acc" (insn-type ins)))
|
||||
(define new-insn
|
||||
(insn (match (insn-type ins) ["jmp" "nop"] ["nop" "jmp"])
|
||||
(insn-arg ins)))
|
||||
(define new-prg (vector-copy input))
|
||||
(vector-set! new-prg i new-insn)
|
||||
(match (execute-program new-prg)
|
||||
[(cons 'loop _) (void)]
|
||||
[(cons 'done acc) (exit acc)]))))
|
||||
(define target-pc (vector-length input))
|
||||
;; create naive CFG (as list of edges)
|
||||
(define model/list
|
||||
(for/list ([i (in-naturals)] [ins (in-vector input)])
|
||||
(match-define (insn type arg) ins)
|
||||
(match type
|
||||
[(or "nop" "acc") (list i (add1 i))]
|
||||
["jmp" (list i (+ i arg))])))
|
||||
;; detect connected components of unweighted CFG
|
||||
(define ccs (map list->set (cc (undirected-graph model/list))))
|
||||
;; 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
|
||||
(define input
|
||||
|
|
Loading…
Reference in New Issue