import csv

def parse_registers(input_path):
    registers = []
    with open(input_path, 'rt') as f_input:
        csv_reader = csv.reader(f_input, delimiter=' ')
        for line in csv_reader:
            registers.append((line[0], tuple(line[1:])))
    return registers

"""
Explanation: Coprocessor Conflagration
End of explanation
"""


from collections import defaultdict
import re

def init(input_path):
    globals()['prog'] = defaultdict(int)
    globals()['mul_count'] = 0
    globals()['registers'] = parse_registers(input_path)
    
def retrieve(string, prog):
    if re.search('\d+', string):
        return int(string)
    else:
        return prog[string]

def r_set(x, y):
    y = retrieve(y, prog)
    prog[x] = y
    
def r_mul(x, y):
    y = retrieve(y, prog)
    prog[x] *= y
    globals()['mul_count'] += 1
    
def r_sub(x, y):
    y = retrieve(y, prog)
    prog[x] -= y

def exec_register(reg):
    comm = reg[0]
    argx = reg[1][0]
    argy = reg[1][1]
    globals()['r_' + comm](argx, argy)

def run_update(registers, initial_head):
    head = initial_head
    while head < len(registers):
        reg = registers[head]
        if reg[0] != 'jnz':
            exec_register(reg)
            head += 1
        else:
            req = retrieve(reg[1][0], prog)
            offset = retrieve(reg[1][1], prog)
            if req != 0:
                head += offset
            else:
                head += 1

"""
Explanation: Part 1
End of explanation
"""


init('input.txt')
run_update(registers, 0)
mul_count

"""
Explanation: Solution
End of explanation
"""


def run_coprocessor_rough(alpha):
    loop0, loop1, loop2 = False, False, False
    a = alpha
    b = 79
    c = b
    d = 0
    e = 0
    f = 0
    g = 0
    h = 0
    if a != 0:
        b *= 100
        b += 100000
        c = b
        c += 17000
    while (g != 0) or not loop0:
        loop0 = True
        f = 1
        d = 2
        while (g != 0) or not loop1:
            loop1 = True
            e = 2
            while (g != 0) or not loop2:
                loop2 = True
                g = d
                g *= e
                g = g - b
                if g == 0:
                    f = 0
                e += 1
                g = e
                g = g - b
            d += 1
            g = d
            g = g - b
        if f == 0:
            h += 1
        g = b
        g = g - c
        if g == 0:
            return a, b, c, d, e, f, g, h
        else:
            b += 17

"""
Explanation: Part 2
If we try the natural stretch of the method devised in Part 1, we got too much running time.
So we will try to figure a straightforward code optimization of the following lines of code:
This is the Python translation of our chunk of assembly code...
End of explanation
"""


run_coprocessor_rough(0)

"""
Explanation: Test
End of explanation
"""


def is_prime(x):
    if x >= 2:
        for y in range(2,x):
            if not ( x % y ):
                return False
    else:
        return False
    return True

def run_coprocessor(alpha):
    loop = False
    a, b = alpha, 79
    c = b
    d, e, f, g, h = 0, 0, 0, 0, 0
    if a != 0:
        b *= 100
        b += 100000
        c = b
        c += 17000
    while (g != 0) or not loop:
        loop = True
        f = 1
        d = 2
        e = 2
        if not is_prime(b):
            f = 0
        e = b
        d = b
        if f == 0:
            h += 1
        g = b
        g = g - c
        if g == 0:
            return a, b, c, d, e, f, g, h
        else:
            b += 17

run_coprocessor(1)

"""
Explanation: Solution
Optimizing little by little, I can manage to reduce it to the following chunk of code.
It turns out that a primality test function is handy.
End of explanation
"""


