diff --git a/2020/day8/day8.ex b/2020/day8/day8.ex index ab9e701..232b750 100644 --- a/2020/day8/day8.ex +++ b/2020/day8/day8.ex @@ -35,6 +35,58 @@ defmodule Day8 do program = parse_program(read_input()) find_loop(program, 0, 0, %{}) end + + def run(program, pc, acc, history, term_pc) do + {next_pc, next_acc} = tick(program, pc, acc) + count = Map.get(history, next_pc, 0) + + cond do + count > 0 -> :loop + next_pc == term_pc -> {:term, next_acc} + next_pc > term_pc -> :wtf + true -> run(program, next_pc, next_acc, Map.put(history, next_pc, count + 1), term_pc) + end + end + + def mod(program, ridx) do + Enum.with_index(program) + |> Enum.map(fn {{op, val}, idx} -> + if idx == ridx do + case op do + "nop" -> {"jmp", val} + "jmp" -> {"nop", val} + _ -> {op, val} + end + else + {op, val} + end + end) + end + + def mods(program) do + Stream.with_index(program) + |> Stream.filter(fn {{op, _val}, _idx} -> + case op do + "acc" -> false + "nop" -> true + "jmp" -> true + end + end) + |> Stream.map(fn {_, idx} -> mod(program, idx) end) + end + + def part2 do + program = parse_program(read_input()) + term_pc = Enum.count(program) + + Enum.reduce_while(mods(program), nil, fn modded_program, _ -> + case run(modded_program, 0, 0, %{}, term_pc) do + :loop -> {:cont, nil} + {:term, acc} -> {:halt, acc} + end + end) + end end Day8.part1() |> IO.inspect() +Day8.part2() |> IO.inspect()