Untitled

 avatar
unknown
python
3 years ago
2.7 kB
7
Indexable
%%time
from collections import defaultdict

def solve(inp_filename):
    with open(inp_filename) as file:
        lines = [s.strip() for s in file.readlines() if len(s.strip()) > 0]
        
    def execute(commands, state, inp):
        i = 0
        for line in commands:
            parts = line.split()
            if parts[0] == 'inp':
                if i >= len(inp):
                    print(f"asking too much {i}, {inp}")
                state[parts[1]] = inp[i]
                i += 1
            else:
                x = parts[1]
                if parts[2][0] in 'xyzw':
                    y = state[parts[2]]
                else:
                    y = int(parts[2])
                if parts[0] == 'add':
                    state[x] += y
                elif parts[0] == 'mul':
                    state[x] *= y
                elif parts[0] == 'div':
                    if y == 0:
                        print(f"y=0 for command {line}")
                        raise 1
                    state[x] = state[x] // y
                elif parts[0] == 'mod':
                    if y == 0:
                        print(f"y=0 for command {line}")
                        raise 1
                    state[x] = state[x] % y
                elif parts[0] == 'eql':
                    state[x] = 1 if (state[x] == y) else 0
        return state

    def group_commads_by_blocks(lines):
        start = 0
        blocks = []
        for end in range(1, len(lines) + 1):
            if end == len(lines) or lines[end].startswith('inp'):
                blocks.append(lines[start : end])
                start = end
        return blocks
    
    def execute_blocks(blocks, state, inp):
        for i, block in enumerate(blocks):
            state = execute(block, state, [inp[i]])
        return state
    
    blocks = group_commads_by_blocks(lines)
        
    needz = defaultdict(lambda: float('inf'))
    needz[0] = 0
    power = 1
    maxz_ranges = [1, 20, 500] + [13000, 320000, 13000, 320000, 13000, 320000, 13000] + [1000, 100, 100, 100]
    for bi in range(len(blocks) - 1, -1, -1):
        block = blocks[bi]
        new_needz = defaultdict(lambda: float('inf'))
        for w in range(1, 10):
            for inputz in range(maxz_ranges[bi]):
                state = execute(block, {'x':0, 'y':0, 'z':inputz, 'w':0}, [w])
                if state['z'] in needz:
                    new_needz[inputz] = min(new_needz[inputz], w * power + needz[state['z']])
        needz = new_needz
        power *= 10
        print(bi, len(needz), min(needz), max(needz))
        
    return needz
        
#     print(execute_blocks(blocks[3:], {'x':0, 'y':0, 'z':3, 'w':0}, list(map(int, '92999192998'))))
    
        
solve('input')