#lang curly-fn racket (require "scripts/aoc.rkt") ;; solution for day 8 (struct insn [type arg] #:transparent) ;; helper functions here (define (execute-program prg) (define (execute pc acc [seen (mutable-set)]) (cond [(set-member? seen pc) (cons 'loop acc)] [(>= pc (vector-length prg)) (cons 'done acc)] [else (match-define (insn type arg) (vector-ref prg pc)) (set-add! seen pc) (match type ["nop" (execute (add1 pc) acc seen)] ["jmp" (execute (+ pc arg) acc seen)] ["acc" (execute (add1 pc) (+ acc arg) seen)])])) (execute 0 0)) (define (part1 input) (cdr (execute-program input))) (define (part2 input) (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 (for/vector ([line (in-list (file->lines "inputs/8"))]) (match (string-split line) [(list a b) (insn a (string->number b))] [x (error "not shonks" x)]))) ;; part 1 (answer 8 1 (part1 input)) ;; part 2 (answer 8 2 (part2 input)) (displayln "meow"))