diff --git a/console.cr b/console.cr new file mode 100644 index 0000000..0004262 --- /dev/null +++ b/console.cr @@ -0,0 +1,36 @@ +def parse(input) + input.lines.map do |s| + code, int = s.split(" ") + {code, int.to_i32} + end +end + +def run(prog) + acc = 0 + pc = 0 + visited = Set(Int32).new + input = Channel(Int32).new + output = Channel({Symbol, Int32}).new + spawn do + loop do + if pc >= prog.size + output.send({:term, acc}) + break + elsif visited.includes? pc + output.send({:inf, acc}) + break + end + + visited << pc + code, int = prog[pc] + case code + when "acc" + acc += int + when "jmp" + pc += int - 1 + end + pc += 1 + end + end + {input, output} +end diff --git a/day8.cr b/day8.cr index c9bb8c7..9205b95 100644 --- a/day8.cr +++ b/day8.cr @@ -1,41 +1,21 @@ require "advent" -INPUT = input(2020, 8).lines.map do |s| - code, int = s.split(" ") - {code, int.to_i32} -end +require "./console.cr" -def run(prog) - acc = 0 - pc = 0 - visited = Set(Int32).new - loop do - return {:term, acc} if pc >= prog.size - return {:inf, acc} if visited.includes? pc - - visited << pc - code, int = prog[pc] - case code - when "acc" - acc += int - when "jmp" - pc += int - 1 - end - pc += 1 - end -end +INPUT = input(2020, 8) def part1 - run(INPUT)[1] + run(parse(INPUT))[1].receive[1] end def part2 - jnp = INPUT.find_indices { |e| e[0] == "jmp" || e[0] == "nop" } + input = parse(INPUT) + jnp = input.find_indices { |e| e[0] == "jmp" || e[0] == "nop" } jnp.each do |i| - prog = INPUT.clone + prog = input.clone op, int = prog[i] prog[i] = {op.tr("jmpnop", "nopjmp"), int} - code, acc = run(prog) + code, acc = run(prog)[1].receive return acc if code == :term end end