๐Ÿ“ฆ Bogdanp / aoc2020

๐Ÿ“„ day08.rkt ยท 69 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69#lang racket/base

(require racket/match
         racket/set
         racket/vector)

(struct instr (opcode arg)
  #:transparent)

(define (parse-instr line)
  (match (regexp-match #rx"^(acc|jmp|nop) (.+)$" line)
    [(list _
           (app string->symbol op)
           (app string->number arg))
     (instr op arg)]))

(define instrs
  (call-with-input-file "input08.txt"
    (lambda (in)
      (for/vector ([line (in-lines in)])
        (parse-instr line)))))

(define (step instrs pc acc)
  (match (vector-ref instrs pc)
    [(instr 'nop _)   (values (add1 pc) acc)]
    [(instr 'acc arg) (values (add1 pc) (+ acc arg))]
    [(instr 'jmp arg) (values (+ pc arg) acc)]))

(define (interp instrs)
  (let loop ([pc 0]
             [acc 0]
             [seen (set)])
    (define-values (new-pc new-acc)
      (step instrs pc acc))
    (cond
      [(set-member? seen new-pc)
       (values 'break new-acc)]
      [(< new-pc (vector-length instrs))
       (loop new-pc new-acc (set-add seen pc))]
      [else
       (values 'end acc)])))

(define (patch-instrs instrs pc)
  (define new-instrs (vector-copy instrs))
  (define new-instr
    (match (vector-ref new-instrs pc)
      [(instr 'nop arg) (instr 'jmp arg)]
      [(instr 'jmp arg) (instr 'nop arg)]))
  (begin0 new-instrs
    (vector-set! new-instrs pc new-instr)))

(define (fix-instrs/brute-force instrs)
  (define poss-to-patch
    (for/list ([(i pc) (in-indexed instrs)]
               #:when (or (eq? (instr-opcode i) 'nop)
                          (eq? (instr-opcode i) 'jmp)))
      pc))
  (for*/or ([pc (in-list poss-to-patch)]
            [patched-instrs (in-value (patch-instrs instrs pc))])
    (define-values (exit acc)
      (interp patched-instrs))
    (and (eq? exit 'end) acc)))

(define-values (_ broken-acc)
  (interp instrs))

(define patched-acc
  (fix-instrs/brute-force instrs))