<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
Step1:  Day 7
Day 7.1
Approach 1
Step2:  Test
Step4:  This approach seems correct, but it creates huge expressions along the way that become harder and harder to parse. Thus the time to a final expression that wraps up all the computations is very long. Two ideas to carry on
Step5:  Test 0
Step6:  Test 1
Step7:  Solution
Step9:  Approach 3
Step10:  Test
Step11:  Although the approach passes the test, it does not end in reasonable time for the full input.
Approach 4
Step12:  Test
Step13:  Solution
Step14:  Although this approach is more natural than defining a LazyWrapper in Python, it takes quite a lot of time to execute, so this is not a very cool solution after all.
Day 7.2
<ASSISTANT_TASK:>
Python Code:
binary_command = {'NOT': '~', 'AND': '&', 'OR': '|', 'LSHIFT': '<<', 'RSHIFT': '>>'}
operators = binary_command.values()
import csv
def translate(l):
    return [binary_command[a] if a in binary_command else a for a in l]
def display(input_file):
    produce a dict mapping variables to expressions
    
    commands = []
    with open(input_file, 'rt') as f_input:
        csv_reader = csv.reader(f_input, delimiter=' ')
        for line in csv_reader:
            commands.append((line[-1], ' '.join(list(translate(line[:-2])))))
    return dict(commands)
import re
def extract_variables(expr):
    varbls = []
    regex_pattern = '\s|\\)|\\('
    l = re.split(regex_pattern, expr)
    for a in l:
        if (a not in operators) and (not a.isnumeric()) and (a != ''):
            varbls.append(a)
    return set(varbls)
def create_instance(wire):
    exec_python = commands[wire]
    pending = extract_variables(commands[wire])
    count = 0
    while pending and (count < 200):
        s = pending.pop()
        expr = commands[s]
        exec_python = re.sub('({0})'.format(s), '( {0} )'.format(expr), exec_python)
        pending = pending.union(extract_variables(exec_python))
        count += 1
    return wire + ' = ' + exec_python
def evaluate(var):
    instance = create_instance(var)
    exec(instance)
    return np.uint16(locals()[var])
Explanation: Day 7
Day 7.1
Approach 1: Create a single expression by recursive substitution, then evaluate!
End of explanation
commands = display('inputs/input7.test.txt')
def test():
    assert(evaluate('d') == 72)
    assert(evaluate('e') == 507)
    assert(evaluate('f') == 492)
    assert(evaluate('g') == 114)
    assert(evaluate('h') == 65412)
    assert(evaluate('i') == 65079)
    assert(evaluate('x') == 123)
    assert(evaluate('y') == 456)
test()
Explanation: Test
End of explanation
import numpy as np
def RSHIFT(a, b):
    result = np.uint16(a) >> int(b)
    return int(result)
def LSHIFT(a, b):
    result = np.uint16(a) << int(b)
    return int(result)
def OR(a, b):
    result = np.uint16(a) | np.uint16(b)
    return int(result)
def AND(a, b):
    result = np.uint16(a) & np.uint16(b)
    return int(result)
def NOT(a):
    result = ~ np.uint16(a)
    return int(result)
import csv
def display(input_file):
    produce a dict mapping variables to expressions
    
    commands = []
    with open(input_file, 'rt') as f_input:
        csv_reader = csv.reader(f_input, delimiter=' ')
        for line in csv_reader:
            commands.append((line[-1], line[:-2]))
    return dict(commands)
def evaluate(wire):
    known = {}
    while wire not in known:
        if wire in known:
            break
        for k, v in commands.items():
            if (len(v) == 1) and (v[0].isnumeric()) and (k not in known):
                known[k] = int(v[0])
            elif (len(v) == 1) and (v[0] in known) and (k not in known):
                known[k] = known[v[0]]
            elif ('AND' in v) and (v[0] in known) and (v[2] in known):
                known[k] = AND(known[v[0]], known[v[2]])
            elif ('AND' in v) and (v[0].isnumeric()) and (v[2] in known):
                known[k] = AND(int(v[0]), known[v[2]])
            elif ('AND' in v) and (v[0] in known) and (v[2].isnumeric()):
                known[k] = AND(known[v[0]], int(v[2]))
            elif ('OR' in v) and (v[0] in known) and (v[2] in known):
                known[k] = OR(known[v[0]], known[v[2]])
            elif ('OR' in v) and (v[0].isnumeric()) and (v[2] in known):
                known[k] = OR(int(v[0]), known[v[2]])
            elif ('OR' in v) and (v[0] in known) and (v[2].isnumeric()):
                known[k] = OR(known[v[0]], int(v[2]))
            elif ('LSHIFT' in v) and (v[0] in known):
                known[k] = LSHIFT(known[v[0]], v[2])
            elif ('RSHIFT' in v) and (v[0] in known):
                known[k] = RSHIFT(known[v[0]], v[2])
            elif ('NOT' in v) and (v[1] in known):
                known[k] = NOT(known[v[1]])
    return known[wire]
Explanation: This approach seems correct, but it creates huge expressions along the way that become harder and harder to parse. Thus the time to a final expression that wraps up all the computations is very long. Two ideas to carry on: i) concurrent evaluation of expressions; ii) define lazy variables/functions that collect all the dependencies of the circuit and start firing upon request.
Approach 2: Concurrent evaluation from known variables.
The solution provided hereto owes credit to this source: https://www.reddit.com/r/adventofcode/comments/5id6w0/2015_day_7_part_1_python_wrong_answer/
End of explanation
commands = display('inputs/input7.test1.txt')
commands
evaluate('a')
Explanation: Test 0
End of explanation
commands = display('inputs/input7.test2.txt')
commands
test()
Explanation: Test 1
End of explanation
commands = display('inputs/input7.txt')
evaluate('a')
Explanation: Solution
End of explanation
import csv
import numpy as np
def display(input_file):
    produce a dict mapping variables to expressions
    
    commands = []
    with open(input_file, 'rt') as f_input:
        csv_reader = csv.reader(f_input, delimiter=' ')
        for line in csv_reader:
            commands.append((line[-1], line[:-2]))
    return dict(commands)
class LazyVar(object):
    def __init__(self, func):
        self.func = func
        self.value = None
    def __call__(self):
        if self.value is None:
            self.value = self.func()
        return self.value
binary_command = {'NOT': '~', 'AND': '&', 'OR': '|', 'LSHIFT': '<<', 'RSHIFT': '>>'}
def translate(l):
    translated = []
    for a in l:
        if a in binary_command:
            b = binary_command[a]
        elif a.isnumeric():
            b = 'np.uint16({})'.format(a)
        else:
            b = '{}.func()'.format('var_' + a)
        translated.append(b)
    return translated
Explanation: Approach 3: With Lazy Variable Wrapper (Python)
End of explanation
commands = display('inputs/input7.test2.txt')
commands = display('inputs/input7.test2.txt')
for k, v in commands.items():
    command_str = '{0} = LazyVar(lambda: {1})'.format('var_' + k, ''.join(translate(v)))
    print(command_str)
    exec(command_str)
def test():
    assert(var_d.func() == 72)
    assert(var_e.func() == 507)
    assert(var_f.func() == 492)
    assert(var_g.func() == 114)
    assert(var_h.func() == 65412)
    assert(var_i.func() == 65079)
    assert(var_x.func() == 123)
    assert(var_y.func() == 456)
test()
Explanation: Test
End of explanation
def rscript_command(var, l):
    vocab =  {'AND'    : 'bitwAnd', 
              'OR'     : 'bitwOr',
              'LSHIFT' : 'bitwShiftL',
              'RSHIFT' : 'bitwShiftR'}
    if len(l) == 3:
        func = vocab[l[1]]
        arg1 = l[0] if l[0].isdigit() else 'var_' + l[0] + '()'
        arg2 = l[2] if l[2].isdigit() else 'var_' + l[2] + '()'
        return 'var_{0} <- function(a={1}, b={2})'.format(var, arg1, arg2) + ' {' + '{0}(a,b)'.format(func) + '}'
    elif len(l) == 2:
        func = 'bitwNot'
        arg1 = l[1] if l[1].isdigit() else 'var_' + l[1] + '()'
        return 'var_{0} <- function(a={1})'.format(var, arg1) + ' {' + '{0}(a)'.format(func) + '}'
    else:
        arg1 = l[0] if l[0].isdigit() else 'var_' + l[0] + '()'
        return 'var_{0} <- function(a={1})'.format(var, arg1) + ' {' + 'a' + '}'
def generate_rscript(commands, target):
    with open('day7_commands.R', 'wt') as f:
        for k, v in commands.items():
            f.write(rscript_command(k, v)+'\n')
        f.write('var_' + target + '()')
Explanation: Although the approach passes the test, it does not end in reasonable time for the full input.
Approach 4: With Lazy Evaluation in R
The approach now is to exploit the lazy evaluation capabilities in R. So we leverage Python to create an R script that does the job.
End of explanation
commands = display('inputs/input7.test2.txt')
generate_rscript(commands, 'd')
! cat day7_commands.R
!Rscript day7_commands.R
Explanation: Test
End of explanation
commands = display('inputs/input7.txt')
generate_rscript(commands, 'a')
! cat day7_commands.R 
!Rscript day7_commands.R
Explanation: Solution
End of explanation
commands = display('inputs/input7.txt')
commands['b'] = ['16076']
evaluate('a')
Explanation: Although this approach is more natural than defining a LazyWrapper in Python, it takes quite a lot of time to execute, so this is not a very cool solution after all.
Day 7.2
End of explanation
<END_TASK>