Created
December 11, 2015 06:57
-
-
Save kiriappeee/df673db3a924385281b7 to your computer and use it in GitHub Desktop.
Advent of code day 7 solution (http://adventofcode.com/day/7)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import struct | |
import re | |
#NOTE that the input file given below won't be the same if you sign up for advent of code to try it out yourself. | |
#let me know if it doesn't work for you | |
circuit = {} | |
def parseInstruction(instruction): | |
instructionBreakDown = dict() | |
if re.search(r'AND|OR', instruction): | |
result = re.findall(r'(\w+|\d+) (AND|OR) (\w+) -> (\w+)', instruction)[0] | |
instructionBreakDown['inputs'] = [result[0], result[2]] | |
instructionBreakDown['output'] = result[3] | |
instructionBreakDown['operator'] = result[1] | |
elif re.search(r'NOT', instruction): | |
result = re.findall(r'(NOT) (\w+) -> (\w+)', instruction)[0] | |
instructionBreakDown['inputs'] = [result[1]] | |
instructionBreakDown['output'] = result[2] | |
instructionBreakDown['operator'] = result[0] | |
elif re.search(r'(RSHIFT|LSHIFT)', instruction): | |
result = re.findall(r'(\w+|\d+) (RSHIFT|LSHIFT) (\d+) -> (\w+)', instruction)[0] | |
instructionBreakDown['inputs'] = [result[0]] | |
instructionBreakDown['output'] = result[3] | |
instructionBreakDown['operator'] = result[1] | |
instructionBreakDown['shift'] = int(result[2]) | |
elif re.search(r'^\w+|\d+ ->', instruction): | |
result = re.findall(r'^(\w+|\d+) -> (\w+)', instruction)[0] | |
instructionBreakDown['inputs'] = [result[0]] | |
instructionBreakDown['output'] = result[1] | |
instructionBreakDown['operator'] = '' | |
return instructionBreakDown | |
def execute(instruction): | |
global circuit | |
instructionBreakDown = parseInstruction(instruction) | |
if instructionBreakDown['operator'] == '': | |
inputs = instructionBreakDown['inputs'] | |
output = instructionBreakDown ['output'] | |
inputs[0] = addInputToCircuit(inputs[0], output) | |
addOutputToCircuit(output, inputs[0], None) | |
elif instructionBreakDown['operator'] == 'AND' or instructionBreakDown['operator'] == 'OR': | |
output = instructionBreakDown ['output'] | |
inputs = instructionBreakDown['inputs'] | |
inputs[0] = addInputToCircuit(inputs[0], output) | |
inputs[1] = addInputToCircuit(inputs[1], output) | |
addOutputToCircuit(output, inputs, instructionBreakDown['operator']) | |
elif instructionBreakDown['operator'] == 'NOT': | |
output = instructionBreakDown ['output'] | |
inputs = instructionBreakDown['inputs'] | |
inputs[0] = addInputToCircuit(inputs[0], output) | |
addOutputToCircuit(output, inputs, instructionBreakDown['operator']) | |
elif instructionBreakDown['operator'] == 'RSHIFT' or instructionBreakDown['operator'] == 'LSHIFT': | |
output = instructionBreakDown ['output'] | |
inputs = instructionBreakDown['inputs'] | |
inputs[0] = addInputToCircuit(inputs[0], output) | |
addOutputToCircuit(output, inputs, instructionBreakDown['operator'], shift=instructionBreakDown['shift']) | |
def addInputToCircuit(input, output): | |
global circuit | |
if input.isdigit(): | |
input = int(input) | |
else: | |
if input not in circuit.keys(): | |
circuit[input] = {'inputs': [], 'operator': None, 'connected': [output]} | |
else: | |
circuit[input]['connected'].append(output) | |
return input | |
def addOutputToCircuit(output, inputs, operator, shift=None): | |
global circuit | |
if output not in circuit.keys(): | |
circuit[output] = {'inputs': inputs, | |
'operator': operator, 'connected': []} | |
else: | |
circuit[output]['inputs'] = inputs | |
circuit[output]['operator'] = operator | |
if shift: | |
circuit[output]['shift'] = shift | |
def getCircuit(): | |
global circuit | |
return circuit | |
calculatedValues = {} | |
def getNodeValue(node): | |
global calculatedValues | |
global circuit | |
nodeItem = circuit.get(node) | |
if type(node) is int: | |
return node | |
if node in calculatedValues.keys(): | |
return calculatedValues[node] | |
if nodeItem['operator'] is None: | |
if type(nodeItem['inputs']) is int: | |
return nodeItem['inputs'] | |
else: | |
return getNodeValue(nodeItem['inputs']) | |
if nodeItem['operator'] == 'AND': | |
value = getNodeValue(nodeItem['inputs'][0]) & getNodeValue(nodeItem['inputs'][1]) | |
if nodeItem['operator'] == 'OR': | |
value = getNodeValue(nodeItem['inputs'][0]) | getNodeValue(nodeItem['inputs'][1]) | |
if nodeItem['operator'] == 'LSHIFT': | |
value = getNodeValue(nodeItem['inputs'][0]) << nodeItem['shift'] | |
if nodeItem['operator'] == 'RSHIFT': | |
value = getNodeValue(nodeItem['inputs'][0]) >> nodeItem['shift'] | |
if nodeItem['operator'] == 'NOT': | |
value = struct.unpack('H', struct.pack('h', ~getNodeValue(nodeItem['inputs'][0])))[0] | |
calculatedValues[node] = value | |
return value | |
def runPartOne(): | |
f = open('day7input', 'r') | |
instructions = f.readlines() | |
for instruction in instructions: | |
execute(instruction) | |
print(getNodeValue('a')) | |
def runPartTwo(): | |
global calculatedValues | |
f = open('day7input', 'r') | |
instructions = f.readlines() | |
for instruction in instructions: | |
execute(instruction) | |
valueOfA = getNodeValue('a') | |
calculatedValues = {} | |
calculatedValues['b'] = valueOfA | |
print(getNodeValue('a')) | |
if __name__ == "__main__": | |
runPartOne() | |
runPartTwo() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
lf AND lq -> ls | |
iu RSHIFT 1 -> jn | |
bo OR bu -> bv | |
gj RSHIFT 1 -> hc | |
et RSHIFT 2 -> eu | |
bv AND bx -> by | |
is OR it -> iu | |
b OR n -> o | |
gf OR ge -> gg | |
NOT kt -> ku | |
ea AND eb -> ed | |
kl OR kr -> ks | |
hi AND hk -> hl | |
au AND av -> ax | |
lf RSHIFT 2 -> lg | |
dd RSHIFT 3 -> df | |
eu AND fa -> fc | |
df AND dg -> di | |
ip LSHIFT 15 -> it | |
NOT el -> em | |
et OR fe -> ff | |
fj LSHIFT 15 -> fn | |
t OR s -> u | |
ly OR lz -> ma | |
ko AND kq -> kr | |
NOT fx -> fy | |
et RSHIFT 1 -> fm | |
eu OR fa -> fb | |
dd RSHIFT 2 -> de | |
NOT go -> gp | |
kb AND kd -> ke | |
hg OR hh -> hi | |
jm LSHIFT 1 -> kg | |
NOT cn -> co | |
jp RSHIFT 2 -> jq | |
jp RSHIFT 5 -> js | |
1 AND io -> ip | |
eo LSHIFT 15 -> es | |
1 AND jj -> jk | |
g AND i -> j | |
ci RSHIFT 3 -> ck | |
gn AND gp -> gq | |
fs AND fu -> fv | |
lj AND ll -> lm | |
jk LSHIFT 15 -> jo | |
iu RSHIFT 3 -> iw | |
NOT ii -> ij | |
1 AND cc -> cd | |
bn RSHIFT 3 -> bp | |
NOT gw -> gx | |
NOT ft -> fu | |
jn OR jo -> jp | |
iv OR jb -> jc | |
hv OR hu -> hw | |
19138 -> b | |
gj RSHIFT 5 -> gm | |
hq AND hs -> ht | |
dy RSHIFT 1 -> er | |
ao OR an -> ap | |
ld OR le -> lf | |
bk LSHIFT 1 -> ce | |
bz AND cb -> cc | |
bi LSHIFT 15 -> bm | |
il AND in -> io | |
af AND ah -> ai | |
as RSHIFT 1 -> bl | |
lf RSHIFT 3 -> lh | |
er OR es -> et | |
NOT ax -> ay | |
ci RSHIFT 1 -> db | |
et AND fe -> fg | |
lg OR lm -> ln | |
k AND m -> n | |
hz RSHIFT 2 -> ia | |
kh LSHIFT 1 -> lb | |
NOT ey -> ez | |
NOT di -> dj | |
dz OR ef -> eg | |
lx -> a | |
NOT iz -> ja | |
gz LSHIFT 15 -> hd | |
ce OR cd -> cf | |
fq AND fr -> ft | |
at AND az -> bb | |
ha OR gz -> hb | |
fp AND fv -> fx | |
NOT gb -> gc | |
ia AND ig -> ii | |
gl OR gm -> gn | |
0 -> c | |
NOT ca -> cb | |
bn RSHIFT 1 -> cg | |
c LSHIFT 1 -> t | |
iw OR ix -> iy | |
kg OR kf -> kh | |
dy OR ej -> ek | |
km AND kn -> kp | |
NOT fc -> fd | |
hz RSHIFT 3 -> ib | |
NOT dq -> dr | |
NOT fg -> fh | |
dy RSHIFT 2 -> dz | |
kk RSHIFT 2 -> kl | |
1 AND fi -> fj | |
NOT hr -> hs | |
jp RSHIFT 1 -> ki | |
bl OR bm -> bn | |
1 AND gy -> gz | |
gr AND gt -> gu | |
db OR dc -> dd | |
de OR dk -> dl | |
as RSHIFT 5 -> av | |
lf RSHIFT 5 -> li | |
hm AND ho -> hp | |
cg OR ch -> ci | |
gj AND gu -> gw | |
ge LSHIFT 15 -> gi | |
e OR f -> g | |
fp OR fv -> fw | |
fb AND fd -> fe | |
cd LSHIFT 15 -> ch | |
b RSHIFT 1 -> v | |
at OR az -> ba | |
bn RSHIFT 2 -> bo | |
lh AND li -> lk | |
dl AND dn -> do | |
eg AND ei -> ej | |
ex AND ez -> fa | |
NOT kp -> kq | |
NOT lk -> ll | |
x AND ai -> ak | |
jp OR ka -> kb | |
NOT jd -> je | |
iy AND ja -> jb | |
jp RSHIFT 3 -> jr | |
fo OR fz -> ga | |
df OR dg -> dh | |
gj RSHIFT 2 -> gk | |
gj OR gu -> gv | |
NOT jh -> ji | |
ap LSHIFT 1 -> bj | |
NOT ls -> lt | |
ir LSHIFT 1 -> jl | |
bn AND by -> ca | |
lv LSHIFT 15 -> lz | |
ba AND bc -> bd | |
cy LSHIFT 15 -> dc | |
ln AND lp -> lq | |
x RSHIFT 1 -> aq | |
gk OR gq -> gr | |
NOT kx -> ky | |
jg AND ji -> jj | |
bn OR by -> bz | |
fl LSHIFT 1 -> gf | |
bp OR bq -> br | |
he OR hp -> hq | |
et RSHIFT 5 -> ew | |
iu RSHIFT 2 -> iv | |
gl AND gm -> go | |
x OR ai -> aj | |
hc OR hd -> he | |
lg AND lm -> lo | |
lh OR li -> lj | |
da LSHIFT 1 -> du | |
fo RSHIFT 2 -> fp | |
gk AND gq -> gs | |
bj OR bi -> bk | |
lf OR lq -> lr | |
cj AND cp -> cr | |
hu LSHIFT 15 -> hy | |
1 AND bh -> bi | |
fo RSHIFT 3 -> fq | |
NOT lo -> lp | |
hw LSHIFT 1 -> iq | |
dd RSHIFT 1 -> dw | |
dt LSHIFT 15 -> dx | |
dy AND ej -> el | |
an LSHIFT 15 -> ar | |
aq OR ar -> as | |
1 AND r -> s | |
fw AND fy -> fz | |
NOT im -> in | |
et RSHIFT 3 -> ev | |
1 AND ds -> dt | |
ec AND ee -> ef | |
NOT ak -> al | |
jl OR jk -> jm | |
1 AND en -> eo | |
lb OR la -> lc | |
iu AND jf -> jh | |
iu RSHIFT 5 -> ix | |
bo AND bu -> bw | |
cz OR cy -> da | |
iv AND jb -> jd | |
iw AND ix -> iz | |
lf RSHIFT 1 -> ly | |
iu OR jf -> jg | |
NOT dm -> dn | |
lw OR lv -> lx | |
gg LSHIFT 1 -> ha | |
lr AND lt -> lu | |
fm OR fn -> fo | |
he RSHIFT 3 -> hg | |
aj AND al -> am | |
1 AND kz -> la | |
dy RSHIFT 5 -> eb | |
jc AND je -> jf | |
cm AND co -> cp | |
gv AND gx -> gy | |
ev OR ew -> ex | |
jp AND ka -> kc | |
fk OR fj -> fl | |
dy RSHIFT 3 -> ea | |
NOT bs -> bt | |
NOT ag -> ah | |
dz AND ef -> eh | |
cf LSHIFT 1 -> cz | |
NOT cv -> cw | |
1 AND cx -> cy | |
de AND dk -> dm | |
ck AND cl -> cn | |
x RSHIFT 5 -> aa | |
dv LSHIFT 1 -> ep | |
he RSHIFT 2 -> hf | |
NOT bw -> bx | |
ck OR cl -> cm | |
bp AND bq -> bs | |
as OR bd -> be | |
he AND hp -> hr | |
ev AND ew -> ey | |
1 AND lu -> lv | |
kk RSHIFT 3 -> km | |
b AND n -> p | |
NOT kc -> kd | |
lc LSHIFT 1 -> lw | |
km OR kn -> ko | |
id AND if -> ig | |
ih AND ij -> ik | |
jr AND js -> ju | |
ci RSHIFT 5 -> cl | |
hz RSHIFT 1 -> is | |
1 AND ke -> kf | |
NOT gs -> gt | |
aw AND ay -> az | |
x RSHIFT 2 -> y | |
ab AND ad -> ae | |
ff AND fh -> fi | |
ci AND ct -> cv | |
eq LSHIFT 1 -> fk | |
gj RSHIFT 3 -> gl | |
u LSHIFT 1 -> ao | |
NOT bb -> bc | |
NOT hj -> hk | |
kw AND ky -> kz | |
as AND bd -> bf | |
dw OR dx -> dy | |
br AND bt -> bu | |
kk AND kv -> kx | |
ep OR eo -> eq | |
he RSHIFT 1 -> hx | |
ki OR kj -> kk | |
NOT ju -> jv | |
ek AND em -> en | |
kk RSHIFT 5 -> kn | |
NOT eh -> ei | |
hx OR hy -> hz | |
ea OR eb -> ec | |
s LSHIFT 15 -> w | |
fo RSHIFT 1 -> gh | |
kk OR kv -> kw | |
bn RSHIFT 5 -> bq | |
NOT ed -> ee | |
1 AND ht -> hu | |
cu AND cw -> cx | |
b RSHIFT 5 -> f | |
kl AND kr -> kt | |
iq OR ip -> ir | |
ci RSHIFT 2 -> cj | |
cj OR cp -> cq | |
o AND q -> r | |
dd RSHIFT 5 -> dg | |
b RSHIFT 2 -> d | |
ks AND ku -> kv | |
b RSHIFT 3 -> e | |
d OR j -> k | |
NOT p -> q | |
NOT cr -> cs | |
du OR dt -> dv | |
kf LSHIFT 15 -> kj | |
NOT ac -> ad | |
fo RSHIFT 5 -> fr | |
hz OR ik -> il | |
jx AND jz -> ka | |
gh OR gi -> gj | |
kk RSHIFT 1 -> ld | |
hz RSHIFT 5 -> ic | |
as RSHIFT 2 -> at | |
NOT jy -> jz | |
1 AND am -> an | |
ci OR ct -> cu | |
hg AND hh -> hj | |
jq OR jw -> jx | |
v OR w -> x | |
la LSHIFT 15 -> le | |
dh AND dj -> dk | |
dp AND dr -> ds | |
jq AND jw -> jy | |
au OR av -> aw | |
NOT bf -> bg | |
z OR aa -> ab | |
ga AND gc -> gd | |
hz AND ik -> im | |
jt AND jv -> jw | |
z AND aa -> ac | |
jr OR js -> jt | |
hb LSHIFT 1 -> hv | |
hf OR hl -> hm | |
ib OR ic -> id | |
fq OR fr -> fs | |
cq AND cs -> ct | |
ia OR ig -> ih | |
dd OR do -> dp | |
d AND j -> l | |
ib AND ic -> ie | |
as RSHIFT 3 -> au | |
be AND bg -> bh | |
dd AND do -> dq | |
NOT l -> m | |
1 AND gd -> ge | |
y AND ae -> ag | |
fo AND fz -> gb | |
NOT ie -> if | |
e AND f -> h | |
x RSHIFT 3 -> z | |
y OR ae -> af | |
hf AND hl -> hn | |
NOT h -> i | |
NOT hn -> ho | |
he RSHIFT 5 -> hh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import unittest | |
import pprint | |
from . import day7 | |
class TestDay7PartOne(unittest.TestCase): | |
def setUp(self): | |
day7.circuit = {} | |
day7.calculatedValues = {} | |
def test_instructionCanBeParsed(self): | |
instructionA = 'lf AND lq -> ls' | |
result = day7.parseInstruction(instructionA) | |
self.assertEqual(result["inputs"], ['lf', 'lq']) | |
self.assertEqual(result["output"], 'ls') | |
self.assertEqual(result["operator"], 'AND') | |
instructionE = 'lf OR lq -> ls' | |
result = day7.parseInstruction(instructionE) | |
self.assertEqual(result["inputs"], ['lf', 'lq']) | |
self.assertEqual(result["output"], 'ls') | |
self.assertEqual(result["operator"], 'OR') | |
instructionF = '1 AND cc -> cd' | |
result = day7.parseInstruction(instructionF) | |
self.assertEqual(result["inputs"], ['1', 'cc']) | |
self.assertEqual(result["output"], 'cd') | |
self.assertEqual(result["operator"], 'AND') | |
instructionB = 'NOT lq -> ls' | |
result = day7.parseInstruction(instructionB) | |
self.assertEqual(result["inputs"], ['lq']) | |
self.assertEqual(result["output"], 'ls') | |
self.assertEqual(result["operator"], 'NOT') | |
instructionC = '123 -> en' | |
result = day7.parseInstruction(instructionC) | |
self.assertEqual(result["inputs"], ['123']) | |
self.assertEqual(result["output"], 'en') | |
self.assertEqual(result["operator"], '') | |
instructionD = 'fo RSHIFT 1 -> az' | |
result = day7.parseInstruction(instructionD) | |
self.assertEqual(result["inputs"], ['fo']) | |
self.assertEqual(result["output"], 'az') | |
self.assertEqual(result["operator"], 'RSHIFT') | |
self.assertEqual(result["shift"], 1) | |
instructionG = 'fo LSHIFT 22 -> az' | |
result = day7.parseInstruction(instructionG) | |
self.assertEqual(result["inputs"], ['fo']) | |
self.assertEqual(result["output"], 'az') | |
self.assertEqual(result["operator"], 'LSHIFT') | |
self.assertEqual(result["shift"], 22) | |
def test_basicAssignmentCreatesCircuit(self): | |
instructionA = '123 -> a' | |
day7.execute(instructionA) | |
self.assertEqual(day7.getCircuit(), {'a': {'inputs': 123, 'operator': None, 'connected': []}}) | |
def test_incompleteInstructionCreatesCircuit(self): | |
instructionA = '123 -> a' | |
day7.execute(instructionA) | |
instructionA = 'a AND b -> c' | |
day7.execute(instructionA) | |
self.assertEqual(day7.getCircuit(), {'a': {'inputs': 123, 'operator': None, 'connected': ['c']}, | |
'b': {'inputs': [], 'operator': None, 'connected': ['c']}, | |
'c': {'inputs': ['a', 'b'], 'operator': 'AND', 'connected': []}}) | |
instructionA = 'NOT d -> b' | |
day7.execute(instructionA) | |
self.assertEqual(day7.getCircuit(), {'a': {'inputs': 123, 'operator': None, 'connected': ['c']}, | |
'b': {'inputs': ['d'], 'operator': 'NOT', 'connected': ['c']}, | |
'c': {'inputs': ['a', 'b'], 'operator': 'AND', 'connected': []}, | |
'd': {'inputs': [], 'operator': None, 'connected': ['b']}}) | |
instructionA = 'a RSHIFT 2 -> d' | |
day7.execute(instructionA) | |
self.assertEqual(day7.getCircuit(), {'a': {'inputs': 123, 'operator': None, 'connected': ['c', 'd']}, | |
'b': {'inputs': ['d'], 'operator': 'NOT', 'connected': ['c']}, | |
'c': {'inputs': ['a', 'b'], 'operator': 'AND', 'connected': []}, | |
'd': {'inputs': ['a'], 'operator': 'RSHIFT', 'shift': 2, 'connected': ['b']}}) | |
def test_individualValueCanBeCalculatedWhenCircuitIsCompleted(self): | |
instruction = 'x AND y -> d' | |
day7.execute(instruction) | |
instruction = 'x OR y -> e' | |
day7.execute(instruction) | |
instruction = 'x LSHIFT 2 -> f' | |
day7.execute(instruction) | |
instruction = 'y RSHIFT 2 -> g' | |
day7.execute(instruction) | |
instruction = 'NOT x -> h' | |
day7.execute(instruction) | |
instruction = 'NOT y -> i' | |
day7.execute(instruction) | |
instruction = '123 -> x' | |
day7.execute(instruction) | |
instruction = '456 -> y' | |
day7.execute(instruction) | |
pp = pprint.PrettyPrinter(indent=2) | |
pp.pprint(day7.getCircuit()) | |
self.assertEqual(day7.getNodeValue('x'), 123) | |
self.assertEqual(day7.getNodeValue('y'), 456) | |
self.assertEqual(day7.getNodeValue('d'), 72) | |
self.assertEqual(day7.getNodeValue('e'), 507) | |
self.assertEqual(day7.getNodeValue('f'), 492) | |
self.assertEqual(day7.getNodeValue('g'), 114) | |
self.assertEqual(day7.getNodeValue('h'), 65412) | |
self.assertEqual(day7.getNodeValue('i'), 65079) | |
def test_recursiveCircuitIsCheckedCorrectly(self): | |
instruction = 'x -> a' | |
day7.execute(instruction) | |
instruction = 'z AND b -> x' | |
day7.execute(instruction) | |
instruction = 'e AND f -> b' | |
day7.execute(instruction) | |
instruction = 'e OR f -> z' | |
day7.execute(instruction) | |
instruction = '1 -> e' | |
day7.execute(instruction) | |
instruction = '2 -> f' | |
day7.execute(instruction) | |
print(day7.getNodeValue('a')) | |
if __name__ == "__main__": | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment