Day 23

We have a variation on the 'register' problem from before. I'm not quite sure what's so different here as this doesn't seem super different... Wish I could see part 2 as that would help me decide how to program the first part.

set X Y sets register X to the value of Y. sub X Y decreases register X by the value of Y. mul X Y sets register X to the result of multiplying the value contained in register X by the value of Y. jnz X Y jumps with an offset of the value of Y, but only if the value of X is not zero. (An offset of 2 skips the next instruction, an offset of -1 jumps to the previous instruction, and so on.)

In [1]:
# Load and format instructions:
from string import ascii_letters
instructions = open('H:/python_jiggering/day23_input.txt').readlines()
instructions
instructions = [x.replace('\n', '') for x in instructions]
instructions[:5]
Out[1]:
['set b 81', 'set c b', 'jnz a 2', 'jnz 1 5', 'mul b 100']
In [2]:
# Configure the registry. I guess I'll start out with out object
# oriented farmework until I know how/if I'll need it.
reg_names = ascii_letters[:8]
reg_names = [let for let in reg_names]
register = dict(zip(reg_names, [0 for x in range(8)]))
register
Out[2]:
{'a': 0, 'b': 0, 'c': 0, 'd': 0, 'e': 0, 'f': 0, 'g': 0, 'h': 0}
In [3]:
def read_inst(register, pos):
    inst = instructions[pos]
    inst = inst.split(' ')
    if inst[2] in register.keys():
        inst[2] = register[inst[2]]
    else:
        inst[2] = int(inst[2])
    mul = 0
    # go through the cases:
    if inst[0] == 'set':
        register[inst[1]] = inst[2]
    elif inst[0] == 'sub':
        register[inst[1]] -= inst[2]
    elif inst[0] == 'mul':
        register[inst[1]] *= inst[2]
        mul = 1
    else:
        if inst[1] in register.keys():
            test = register[inst[1]]
        else:
            test = int(inst[1])
        if test != 0:
            pos += inst[2]
            return(register, pos, mul)
    pos += 1
    return(register, pos, mul)

Now do the loop de loop

In [4]:
reg_copy = register.copy()
position = 0
mul_count = 0
while 0 <= position < len(instructions):
    reg_copy, position, mul = read_inst(reg_copy, position)
    mul_count += mul
mul_count
Out[4]:
6241

Well that was quite easy. I'm confused why this was even a puzzle? It doesn't seem any different than the last one...

Part 2

Now we're asked about what happens to cell 'h' when the program is run with a 1 set to cell 'a'. It has some mention of optimization which makes me think that simply re-running this will be impossible. I did try that and it seems to not complete. I suspect this means that we enter into some kind of infinite loop

I'm kind of wondering if a lot of these instructions are basically pointless if we only want to know the value of the h registry. This feels like a bit of a weird approach but I think I'm going to see if I can just condense some of these steps... I'm mostly concerned with the h -= 1 and the jumps.

This is the only problem I've really needed to get help on. I saw someone else organize the instructions with indentations to show the loops. This helped me see that basically what's happening is that we're repeatedly testing if a number is a prime. If it is not, we will add 1 to the count. Each step of the loop we increase by 17.

In [5]:
import math
# use this function to determine if it's a prime
def is_not_prime(x):
    rt = int(math.sqrt(x))
    for i in range(2, rt + 1):
        if x % i == 0:
            return(1)
    else:
        return(0)

# Here's the result of the first 8 lines:

b = 81 * 100 + 100000
c = b + 17000
count = 0
# now we start a loop:
for i in range(1001):
    count += is_not_prime(b)
    b += 17
count
Out[5]:
909