mutable struct Machine
    acc::Int
end
Machine() = Machine(0)

reset!(m::Machine) = (m.acc = 0; m)

function execute!(mach::Machine, program)
    i, N = 1, length(program)
    seen = falses(N)
    while i ≤ N && !seen[i]
        seen[i] = true
        op, arg = program[i]
        if op == "acc"
            mach.acc += arg
            i += 1
        elseif op == "jmp"
            i += arg
        elseif op == "nop"
            i += 1
        end
    end
    i != length(program) + 1, mach.acc
end

function main()
    part1 = -1

    lines = map(readlines("input.txt")) do line
        op, arg = split(line)
        (op, parse(Int, arg))
    end

    machine = Machine()

    _, part1 = execute!(machine, lines)

    for i in findall(l -> first(l) == "jmp", lines)
        reset!(machine)

        lines[i] = ("nop", last(lines[i]))
        early, value = execute!(machine, lines)
        lines[i] = ("jmp", last(lines[i]))
        if !early
            return part1, value
        end
    end

    for i in findall(l -> first(l) == "nop", lines)
        reset!(machine)

        lines[i] = ("jmp", last(lines[i]))
        early, value = execute!(machine, lines)
        lines[i] = ("nop", last(lines[i]))
        if !early
            return part1, value
        end
    end

    error("failed to debug")
end

let (part1, part2) = main()
    @info "Solutions" part1 part2
end
