Skip to content

Instantly share code, notes, and snippets.

@musabkilic
Created December 24, 2019 16:59
Show Gist options
  • Select an option

  • Save musabkilic/09962c3450587c682a7ff087335e6fb9 to your computer and use it in GitHub Desktop.

Select an option

Save musabkilic/09962c3450587c682a7ff087335e6fb9 to your computer and use it in GitHub Desktop.
My Advent of Code 2019 - Day 23 Solution
import os
import sys
import shutil
import time
class InputNeeded(Exception):
pass
class Memory:
def __init__(self, codes):
self.memory = codes
def alloc(self, to):
if len(self.memory) <= to:
#print("ALLOC", to)
self.memory += [0 for i in range(to-len(self.memory)+1)]
def __getitem__(self, x):
self.alloc(x)
return self.memory[x]
def __setitem__(self, ind, v):
self.alloc(ind)
self.memory[ind] = v
def __len__(self):
return len(self.memory)
class Computer:
def __init__(self, codes):
self.codes = Memory(codes[:])
self.ins = 0
self.relative_base = 0
self.halt = False
def apply_mode(self, param, mode, r):
if mode == 0:
return self.codes[param]
elif mode == 1:
return param
elif mode == 2:
#print(param)
#print(self.relative_base)
if r == 0:
return self.relative_base + self.codes[param]
return self.codes[self.relative_base + param]
def get_ins(self):
code = list(map(int, str(self.codes[self.ins]).zfill(5)))
modes = code[:3][::-1]
opcode = code[3] * 10 + code[4]
return modes, opcode
def get_params(self, n, rule={}):
params = []
modes, opcode = self.get_ins()
for i in range(1, n+1):
r = rule.get(i, None)
#print("[00]PARAM:", self.ins+i, modes[i-1], r)
if r == 0:
params.append(self.apply_mode(self.ins+i, modes[i-1], r),)
else:
params.append(self.apply_mode(self.codes[self.ins+i], modes[i-1], r))
#print("[11]PARAM:", i, params[-1])
#print(modes, opcode, params)
if n == 1:
return params[0]
else:
return params
def runProgram(self, inputs=[]):
get_value = lambda x, mode: (x if mode == 1 else (self.codes[x] if mode == 0 else self.codes[self.relative_base + x]))
while self.ins < len(self.codes) and not self.halt:
_, opcode = self.get_ins()
#print()
#print(self.codes.memory)
#print("OPCODE:", opcode, "BASE:", self.relative_base)
if opcode == 1:
j, k, l = self.get_params(3, rule={3:0})
#print("[1]",j, k , l)
self.codes[l] = j + k
self.ins += 4
elif opcode == 2:
j, k, l = self.get_params(3, rule={3:0})
self.codes[l] = j * k
self.ins += 4
elif opcode == 3:
l = self.get_params(1, rule={1:0})
if len(inputs) == 0:
raise InputNeeded
self.codes[l] = inputs.pop(0)
self.ins += 2
elif opcode == 4:
l = self.get_params(1)
#print("[1]", l, )
self.ins += 2
return l
elif opcode == 5:
j, l = self.get_params(2)
if j != 0:
self.ins = l
else:
self.ins += 3
elif opcode == 6:
j, l = self.get_params(2)
#print("[2]", j , l)
if j == 0:
self.ins = l
else:
self.ins += 3
elif opcode == 7:
j, k, l = self.get_params(3, rule={3:0})
self.codes[l] = int(j < k)
self.ins += 4
elif opcode == 8:
j, k, l = self.get_params(3, rule={3:0})
#print("[1]", j, k, l)
self.codes[l] = int(j == k)
self.ins += 4
elif opcode == 9:
j = self.get_params(1)
#print("[1]", self.relative_base, j)
self.relative_base += j
#print("[2]",self.relative_base)
self.ins += 2
elif opcode == 99:
self.halt = True
program = open("23\\input", "r").read().strip()
codes = list(map(int, program.split(",")))
comps = [Computer(codes) for x in range(50)]
queue = [[] for x in range(50)]
proc = [[] for x in range(50)]
for i in range(50):
try:
comps[i].runProgram([i])
except InputNeeded:
pass
NAT = []
while True:
isIdle = True
for i in range(50):
if len(queue[i]) > 0:
isIdle = False
q = queue[i].pop(0)
while True:
try:
proc[i].append(comps[i].runProgram(q))
except InputNeeded:
break
else:
while True:
try:
proc[i].append(comps[i].runProgram([-1]))
except InputNeeded:
break
while len(proc[i]) >= 3:
r = proc[i].pop(0)
X = proc[i].pop(0)
Y = proc[i].pop(0)
if r == 255:
#print(X, Y, r)
NAT = [X, Y]
else:
queue[r].append([X, Y])
if isIdle:
if NAT != []:
print(NAT)
queue[0].append(NAT)
print()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment