Skip to content

Instantly share code, notes, and snippets.

@kiriappeee
Created December 11, 2015 06:57
Show Gist options
  • Save kiriappeee/df673db3a924385281b7 to your computer and use it in GitHub Desktop.
Save kiriappeee/df673db3a924385281b7 to your computer and use it in GitHub Desktop.
Advent of code day 7 solution (http://adventofcode.com/day/7)
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()
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
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