Day 25

Okay we're on to the last one. We have an infinite list of zeroes and instructions that give details on how to change these values and move from them. We have six 'states' that give instructions for whether the current value is a zero or a one. They then direct the state change after execution.

In [1]:
import re
states = open('/Users/Sven/py_files/aoc_2017/day25_input.txt').readlines()
states[:10]
# I lopped off the very top of the input. We'll deal with that in a bit
Out[1]:
['10In state A:\n',
 '  If the current value is 0:\n',
 '    - Write the value 1.\n',
 '    - Move one slot to the right.\n',
 '    - Continue with state B.\n',
 '  If the current value is 1:\n',
 '    - Write the value 0.\n',
 '    - Move one slot to the left.\n',
 '    - Continue with state F.\n',
 '\n']

So it looks like one of the largest challanges here will be parsing the input and choosing a suitable data structure.

In [2]:
def parse_input(line):
    if re.search(r'In state|current', line):
        value = line.split(':')[0]
        value = value.split(' ')
        value = value[-1]
    elif re.search(r'Write|Continue|Move', line):
        value = line.split(' ')
        value = value[-1].replace('\n','').replace('.', '')
    else:
        value = None
    
    # Do some formatting here:
    if value in ['0', '1']:
        value = int(value)
    elif value == 'left':
        value = -1
    elif value == 'right':
        value = 1                  
        
    return(value)

for i in range(5):
    print(parse_input(states[i]))
    
parsed_states = [parse_input(line) for line in states]
parsed_states = [x for x in parsed_states if x is not None]
A
0
1
1
B

Now let's make a dictionary of the values here:

In [3]:
state_dict = dict()
for i in range(6):
    subset = parsed_states[(9*i):(9*i+9)]
    state = subset[0]
    inst1 = subset[1:5]
    inst2 = subset[5:9]
    state_dict.update({state : [inst1, inst2]})
In [4]:
state_dict
Out[4]:
{'A': [[0, 1, 1, 'B'], [1, 0, -1, 'F']],
 'B': [[0, 0, 1, 'C'], [1, 0, 1, 'D']],
 'C': [[0, 1, -1, 'D'], [1, 1, 1, 'E']],
 'D': [[0, 0, -1, 'E'], [1, 0, -1, 'D']],
 'E': [[0, 0, 1, 'A'], [1, 1, 1, 'C']],
 'F': [[0, 1, -1, 'A'], [1, 1, 1, 'A']]}

We'll want a function that can retrieve the information given a state and value:

In [5]:
def retrieve_instructions(state, cell_value):
    inst = state_dict[state]
    if inst[0][0] == cell_value:
        inst = inst[0]
    else:
        inst = inst[1]
    write, move, state = inst[1:]
    return(write, move, state)
retrieve_instructions('F', 1)
Out[5]:
(1, 1, 'A')

Okay that seems like it's going to work. Now we need to set up the tape. I think this will be easier to use with a dictionary as well as we don't want to have to worry about the length of

In [6]:
# initial conditions
tape = dict()
iterations = 12794428
loc = 0
state = 'A'
cell = 0

for i in range(iterations):
    # retrieve the next values
    write, move, state = retrieve_instructions(state, cell)
    # Update the tape
    tape.update({loc : write})
    # move the location and get the new value
    loc += move
    if loc in tape.keys():
        cell = tape[loc]
    else:
        cell = 0
sum(tape.values())
Out[6]:
2832

There is no part 2! Well I really enjoyed working on this project. I feel like I am very far from the Python skillset I want to have, especially with numpy and pandas, but this gave me a lot more familiarity with base Python. I believe that part of the reason I've been a successful R programmer is that I started with the very basic concepts. Hopefully this practice will expedite my learning of more complex modules and topics. I do have some regrets about not trying the object oriented programming paradigm more, as it's not as familiar as functional, but I'm sure we'll get into this