USING: accessors arrays combinators.short-circuit combinators.smart grouping io io.backend io.encodings.utf8 io.files kernel math math.parser models multiline peg.ebnf ranges sequences ; FROM: models => change-model ; IN: advent-of-code.day-10 : get-input-one ( -- seq ) "vocab:advent-of-code/day-10/_input/one.txt" normalize-path utf8 file-contents ; : [-1..+1] ( n -- range ) [ 1 - ] [ 1 + ] bi [a..b] ; TUPLE: addx value ; C: addx TUPLE: noop ; C: noop EBNF: parse-input [=[ number = ("-"? [0-9]+) => [[ "" join dec> ]] addx = "addx "~ number => [[ ]] noop = "noop"~ => [[ ]] instr = (addx | noop) ("\n"?)~ rule = instr* ]=] ! Build the device TUPLE: cpu tick { rx fixnum initial: 1 } { acc fixnum initial: 0 } ; : ( -- cpu ) \ cpu new 0 >>tick ; TUPLE: screen pixels { cursor fixnum initial: 0 } ; : ( -- screen ) \ screen new V{ } clone >>pixels ; TUPLE: device program cpu screen ; : connect-cpu ( device -- ) [ cpu>> ] [ cpu>> tick>> ] bi add-connection ; : connect-screen ( device -- ) [ screen>> ] [ cpu>> tick>> ] bi add-connection ; : ( -- device ) \ device new >>cpu >>screen [ connect-cpu ] [ connect-screen ] [ ] tri ; ! Showing the solutions : show-screen. ( deivce -- ) screen>> pixels>> "" join 40 group "\n" join print ; : show-acc. ( device -- ) cpu>> acc>> >dec print ; ! Updating the CPU : ticks ( cpu -- n ) tick>> value>> ; : twentieth-tick? ( cpu -- ? ) ticks 20 = ; : fourty-ticks? ( cpu -- ? ) ticks 20 - 40 rem zero? ; : strength ( cpu -- n ) [ rx>> ] [ ticks ] bi * ; : track-rx ( cpu -- ) dup [ swap strength + ] change-acc drop ; : track? ( cpu -- ? ) { [ twentieth-tick? ] [ fourty-ticks? ] } 1|| ; M: cpu model-changed nip [ track? ] [ track-rx ] smart-when* ; ! Update the screen : pixel-on? ( cpu screen -- ? ) [ rx>> [-1..+1] ] [ cursor>> ] bi* swap member? ; : on! ( screen -- ) pixels>> "#" suffix! drop ; : off! ( screen -- ) pixels>> "." suffix! drop ; : draw! ( screen ? -- ) [ on! ] [ off! ] if ; : move-cursor! ( screen -- ) [ 1 + 40 rem ] change-cursor drop ; M: screen model-changed [ connections>> first ] dip [ tuck pixel-on? draw! ] [ nip move-cursor! ] 2bi ; ! Running the program : tick! ( cpu -- cpu ) dup tick>> [ 1 + ] change-model ; : addx! ( n cpu -- cpu ) tick! tick! [ + ] change-rx ; : run-instruction ( cpu instruction -- cpu ) [ addx? ] [ value>> swap addx! ] [ tick! ] smart-if* ; : run-program ( program -- device ) [ cpu>> [ run-instruction ] reduce drop ] keep ; ! Solve the problem : solve. ( -- ) get-input-one parse-input run-program [ show-acc. ] [ show-screen. ] bi ;