USING: arrays assocs combinators io.encodings.ascii io.files kernel literals math math.parser namespaces prettyprint qw sequences sets splitting ; FROM: namespaces => set ; IN: aoc.2020.08 CONSTANT: instructions $[ "input.txt" ascii file-lines [ " " split1 string>number swap 2array ] map ] CONSTANT: seen $[ HS{ } clone ] ! Which indices in the instructions have we visited? SYMBOL: iptr ! Instruction pointer; index of the current instruction. SYMBOL: acc : execute-instruction ( -- ) iptr get instructions nth first2 { { "acc" [ acc +@ iptr inc ] } { "jmp" [ iptr +@ ] } [ 2drop iptr inc ] ! nop } case ; : reset ( -- ) 0 iptr set 0 acc set seen clear-set ; : visit ( -- ) iptr get seen adjoin ; : step ( -- ) visit execute-instruction ; : loop? ( -- ? ) iptr get seen in? ; : halted? ( -- ? ) iptr get instructions length >= ; : run ( -- ? ) reset [ loop? halted? or ] [ step ] until halted? ; : part1 ( -- ) run drop acc get . ; ! ~~===={[ PART 2 ]}====~~ : invert-instruction ( index -- ) instructions [ first2 "jmp" = "nop" "jmp" ? 2array ] change-nth ; : invertible? ( seq -- ? ) second qw{ jmp nop } member? ; : invertible ( -- indices ) instructions [ second invertible? ] filter keys ; : attempt-repair ( index -- finished? ) [ invert-instruction run ] [ invert-instruction ] bi ; : part2 ( -- ) invertible [ attempt-repair ] find 2drop acc get . ;