language: racket prompt:


#!/usr/bin/env racket
#lang racket

(define (extract-line line)
    (and (non-empty-string? line) (string-split line " ")))
(define (format-line entry index)
    (list index (first entry) (string->number (second entry))))
(define the-code
    (make-immutable-hash (sequence->list (sequence-map format-line
        (in-indexed (filter-map extract-line
            (file->lines "input")))))))

(define (compute-line addr acc code seen)
        [(set-member? seen addr)
            (eprintf "Error: Attempted to traverse to already seen address.\n")
            (eprintf "addr: ~a\nacc: ~a\n\n" addr acc)
        [(hash-has-key? code addr)
            (let* ([seen (set-add seen addr)]
                   [line (hash-ref code addr)]
                   [op (first line)]
                   [n (second line)])
                (printf "~a: ~a ~a | ~a\n" addr op n acc)
                (let ([addr (case op [("jmp") (+ addr n)] [else (add1 addr)])]
                      [acc (case op [("acc") (+ acc n)] [else acc])])
                    (compute-line addr acc code seen)))]
        [else (printf "Final result: ~a\n\n" acc) #t]))

; Part 1, expected to error out.
(compute-line 0 0 the-code (set))

(print "Type something to continue: ")

; Part 2, searching for a non-error case 
; We can flip one jmp to nop or one nop to jmp.
(define swap (hash "jmp" "nop" "nop" "jmp"))
(define swapped-codes
        (lambda (line)
            (let ([add (first line)]
                  [op (second line)]
                  [n (third line)])
                (and (hash-has-key? swap op)
                     (hash-set the-code add (list (hash-ref swap op) n)))))
        (hash->list the-code)))

(define (run-variant swapped-code)
    (compute-line 0 0 swapped-code (set)))
    (findf run-variant swapped-codes)
    (printf "Done.\n"))