[Python/2019] Restructure solutions

This commit is contained in:
Felix Bargfeldt 2023-10-29 19:47:15 +01:00
parent 40e767096e
commit fb42493fff
Signed by: Defelo
GPG key ID: 2A05272471204DD3
63 changed files with 1393 additions and 1739 deletions

17
Python/2019/01.py Normal file
View file

@ -0,0 +1,17 @@
from lib import *
input = read_input(2019, 1)
out = 0
for line in input.splitlines():
out += int(line) // 3 - 2
print(out)
out = 0
for line in input.splitlines():
fuel = int(line) // 3 - 2
while fuel > 0:
out += fuel
fuel = fuel // 3 - 2
print(out)

View file

@ -1,4 +0,0 @@
out = 0
for line in open("input.txt").read().splitlines():
out += int(line) // 3 - 2
print(out)

View file

@ -1,7 +0,0 @@
out = 0
for line in open("input.txt").read().splitlines():
fuel = int(line) // 3 - 2
while fuel > 0:
out += fuel
fuel = fuel // 3 - 2
print(out)

36
Python/2019/02.py Normal file
View file

@ -0,0 +1,36 @@
from lib import *
input = read_input(2019, 2)
(*mem,) = map(int, input.strip().split(","))
i = 0
mem[1] = 12
mem[2] = 2
while i < len(mem):
if mem[i] == 99:
break
elif mem[i] == 1:
mem[mem[i + 3]] = mem[mem[i + 1]] + mem[mem[i + 2]]
elif mem[i] == 2:
mem[mem[i + 3]] = mem[mem[i + 1]] * mem[mem[i + 2]]
i += 4
print(mem[0])
(*mem,) = map(int, input.strip().split(","))
def simulate(a, b, mem):
i = 0
mem[1] = a
mem[2] = b
while i < len(mem):
if mem[i] == 99:
break
elif mem[i] == 1:
mem[mem[i + 3]] = mem[mem[i + 1]] + mem[mem[i + 2]]
elif mem[i] == 2:
mem[mem[i + 3]] = mem[mem[i + 1]] * mem[mem[i + 2]]
i += 4
return mem[0]
print(*[a * 100 + b for a in range(100) for b in range(100) if simulate(a, b, mem[:]) == 19690720])

View file

@ -1,13 +0,0 @@
*mem, = map(int, open("input.txt").read().strip().split(","))
i = 0
mem[1] = 12
mem[2] = 2
while i < len(mem):
if mem[i] == 99:
break
elif mem[i] == 1:
mem[mem[i+3]] = mem[mem[i+1]] + mem[mem[i+2]]
elif mem[i] == 2:
mem[mem[i+3]] = mem[mem[i+1]] * mem[mem[i+2]]
i += 4
print(mem[0])

View file

@ -1,17 +0,0 @@
*mem, = map(int, open("input.txt").read().strip().split(","))
def simulate(a, b, mem):
i = 0
mem[1] = a
mem[2] = b
while i < len(mem):
if mem[i] == 99:
break
elif mem[i] == 1:
mem[mem[i+3]] = mem[mem[i+1]] + mem[mem[i+2]]
elif mem[i] == 2:
mem[mem[i+3]] = mem[mem[i+1]] * mem[mem[i+2]]
i += 4
return mem[0]
print(*[a * 100 + b for a in range(100) for b in range(100) if simulate(a, b, mem[:]) == 19690720])

40
Python/2019/03.py Normal file
View file

@ -0,0 +1,40 @@
from lib import *
input = read_input(2019, 3)
def parse_wire(wire):
x = 0
y = 0
out = set()
for e in wire.split(","):
dx, dy = {"U": (0, -1), "D": (0, 1), "L": (-1, 0), "R": (1, 0)}[e[0]]
for _ in range(int(e[1:])):
x += dx
y += dy
out.add((x, y))
return out
wire1, wire2 = map(parse_wire, input.splitlines())
print(min(abs(x) + abs(y) for x, y in (wire1 & wire2)))
def parse_wire(wire):
x = 0
y = 0
out = {}
count = 0
for e in wire.split(","):
dx, dy = {"U": (0, -1), "D": (0, 1), "L": (-1, 0), "R": (1, 0)}[e[0]]
for _ in range(int(e[1:])):
x += dx
y += dy
count += 1
if (x, y) not in out:
out[(x, y)] = count
return out
wire1, wire2 = map(parse_wire, input.splitlines())
print(min(wire1[intersection] + wire2[intersection] for intersection in (wire1.keys() & wire2.keys())))

View file

@ -1,14 +0,0 @@
def parse_wire(wire):
x = 0
y = 0
out = set()
for e in wire.split(","):
dx, dy = {"U": (0, -1), "D": (0, 1), "L": (-1, 0), "R": (1, 0)}[e[0]]
for _ in range(int(e[1:])):
x += dx
y += dy
out.add((x, y))
return out
wire1, wire2 = map(parse_wire, open("input.txt").read().splitlines())
print(min(abs(x) + abs(y) for x, y in (wire1 & wire2)))

View file

@ -1,17 +0,0 @@
def parse_wire(wire):
x = 0
y = 0
out = {}
count = 0
for e in wire.split(","):
dx, dy = {"U": (0, -1), "D": (0, 1), "L": (-1, 0), "R": (1, 0)}[e[0]]
for _ in range(int(e[1:])):
x += dx
y += dy
count += 1
if (x, y) not in out:
out[(x, y)] = count
return out
wire1, wire2 = map(parse_wire, open("input.txt").read().splitlines())
print(min(wire1[intersection] + wire2[intersection] for intersection in (wire1.keys() & wire2.keys())))

24
Python/2019/04.py Normal file
View file

@ -0,0 +1,24 @@
from lib import *
input = read_input(2019, 4)
a, b = map(int, input.split("-"))
count = 0
for i in range(a, b + 1):
string = str(i)
if list(string) != sorted(string):
continue
if any(x == y for x, y in zip(string[1:], string)):
count += 1
print(count)
a, b = map(int, input.split("-"))
count = 0
for i in range(a, b + 1):
string = str(i)
if list(string) != sorted(string):
continue
if any(string.count(c) == 2 for c in string):
count += 1
print(count)

View file

@ -1,9 +0,0 @@
a, b = map(int, open("input.txt").read().split("-"))
count = 0
for i in range(a, b + 1):
string = str(i)
if list(string) != sorted(string):
continue
if any(x==y for x, y in zip(string[1:], string)):
count += 1
print(count)

View file

@ -1,9 +0,0 @@
a, b = map(int, open("input.txt").read().split("-"))
count = 0
for i in range(a, b + 1):
string = str(i)
if list(string) != sorted(string):
continue
if any(string.count(c) == 2 for c in string):
count += 1
print(count)

83
Python/2019/05.py Normal file
View file

@ -0,0 +1,83 @@
from lib import *
input = read_input(2019, 5)
(*mem,) = map(int, input.split(","))
pc = 0
while pc < len(mem):
opcode = mem[pc] % 100
mode1 = mem[pc] // 100 % 10
mode2 = mem[pc] // 1000 % 10
if opcode == 1:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
mem[mem[pc + 3]] = arg1 + arg2
pc += 4
elif opcode == 2:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
mem[mem[pc + 3]] = arg1 * arg2
pc += 4
elif opcode == 3:
mem[mem[pc + 1]] = 1
pc += 2
elif opcode == 4:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
if arg1:
print(arg1)
pc += 2
elif opcode == 99:
break
(*mem,) = map(int, input.split(","))
pc = 0
while pc < len(mem):
opcode = mem[pc] % 100
mode1 = mem[pc] // 100 % 10
mode2 = mem[pc] // 1000 % 10
if opcode == 1:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
mem[mem[pc + 3]] = arg1 + arg2
pc += 4
elif opcode == 2:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
mem[mem[pc + 3]] = arg1 * arg2
pc += 4
elif opcode == 3:
mem[mem[pc + 1]] = 5
pc += 2
elif opcode == 4:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
print(arg1)
pc += 2
elif opcode == 5:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
if arg1:
pc = arg2
else:
pc += 3
elif opcode == 6:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
if not arg1:
pc = arg2
else:
pc += 3
elif opcode == 7:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
mem[mem[pc + 3]] = int(arg1 < arg2)
pc += 4
elif opcode == 8:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
mem[mem[pc + 3]] = int(arg1 == arg2)
pc += 4
elif opcode == 99:
break

View file

@ -1,26 +0,0 @@
*mem, = map(int, open("input.txt").read().split(","))
pc = 0
while pc < len(mem):
opcode = mem[pc] % 100
mode1 = mem[pc] // 100 % 10
mode2 = mem[pc] // 1000 % 10
if opcode == 1:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
mem[mem[pc+3]] = arg1 + arg2
pc += 4
elif opcode == 2:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
mem[mem[pc+3]] = arg1 * arg2
pc += 4
elif opcode == 3:
mem[mem[pc+1]] = 1
pc += 2
elif opcode == 4:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
print(arg1)
pc += 2
elif opcode == 99:
break

View file

@ -1,50 +0,0 @@
*mem, = map(int, open("input.txt").read().split(","))
pc = 0
while pc < len(mem):
opcode = mem[pc] % 100
mode1 = mem[pc] // 100 % 10
mode2 = mem[pc] // 1000 % 10
if opcode == 1:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
mem[mem[pc+3]] = arg1 + arg2
pc += 4
elif opcode == 2:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
mem[mem[pc+3]] = arg1 * arg2
pc += 4
elif opcode == 3:
mem[mem[pc+1]] = 5
pc += 2
elif opcode == 4:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
print(arg1)
pc += 2
elif opcode == 5:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
if arg1:
pc = arg2
else:
pc += 3
elif opcode == 6:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
if not arg1:
pc = arg2
else:
pc += 3
elif opcode == 7:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
mem[mem[pc+3]] = int(arg1 < arg2)
pc += 4
elif opcode == 8:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
mem[mem[pc+3]] = int(arg1 == arg2)
pc += 4
elif opcode == 99:
break

39
Python/2019/06.py Normal file
View file

@ -0,0 +1,39 @@
from lib import *
input = read_input(2019, 6)
graph = {}
for line in input.splitlines():
a, b = line.split(")")
graph.setdefault(a, set()).add(b)
out = 0
Q = [("COM", 0)]
while Q:
node, count = Q.pop(0)
out += count
for child in graph.get(node, set()):
Q.append((child, count + 1))
print(out)
graph = {}
for line in input.splitlines():
a, b = line.split(")")
graph.setdefault(a, set()).add(b)
graph.setdefault(b, set()).add(a)
Q = [("YOU", 0)]
visited = set()
while Q:
node, dist = Q.pop(0)
if node in visited:
continue
visited.add(node)
if node == "SAN":
print(dist - 2)
for child in graph.get(node, set()):
Q.append((child, dist + 1))

View file

@ -1,13 +0,0 @@
graph = {}
for line in open("input.txt").read().splitlines():
a, b = line.split(")")
graph.setdefault(a, set()).add(b)
out = 0
Q = [("COM", 0)]
while Q:
node, count = Q.pop(0)
out += count
for child in graph.get(node, set()):
Q.append((child, count + 1))
print(out)

View file

@ -1,19 +0,0 @@
graph = {}
for line in open("input.txt").read().splitlines():
a, b = line.split(")")
graph.setdefault(a, set()).add(b)
graph.setdefault(b, set()).add(a)
Q = [("YOU", 0)]
visited = set()
while Q:
node, dist = Q.pop(0)
if node in visited: continue
visited.add(node)
if node == "SAN":
print(dist - 2)
for child in graph.get(node, set()):
Q.append((child, dist + 1))

157
Python/2019/07.py Normal file
View file

@ -0,0 +1,157 @@
from lib import *
input = read_input(2019, 7)
def intcode(mem, inp):
pc = 0
while pc < len(mem):
opcode = mem[pc] % 100
mode1 = mem[pc] // 100 % 10
mode2 = mem[pc] // 1000 % 10
if opcode == 1:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
mem[mem[pc + 3]] = arg1 + arg2
pc += 4
elif opcode == 2:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
mem[mem[pc + 3]] = arg1 * arg2
pc += 4
elif opcode == 3:
mem[mem[pc + 1]] = inp.pop(0)
pc += 2
elif opcode == 4:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
return arg1
pc += 2
elif opcode == 5:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
if arg1:
pc = arg2
else:
pc += 3
elif opcode == 6:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
if not arg1:
pc = arg2
else:
pc += 3
elif opcode == 7:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
mem[mem[pc + 3]] = int(arg1 < arg2)
pc += 4
elif opcode == 8:
arg1 = mem[pc + 1] if mode1 else mem[mem[pc + 1]]
arg2 = mem[pc + 2] if mode2 else mem[mem[pc + 2]]
mem[mem[pc + 3]] = int(arg1 == arg2)
pc += 4
elif opcode == 99:
break
(*mem,) = map(int, input.split(","))
def test(seq):
out = 0
for i in seq:
out = intcode(mem[:], [i, out])
return out
print(max(test(seq) for seq in itertools.permutations(range(5))))
class IntCode:
def __init__(self, mem):
self.mem = mem
self.pc = 0
self.running = False
self.inp = []
self.out = []
def start(self):
self.running = True
self.cont()
def cont(self):
while self.pc < len(self.mem):
opcode = self.mem[self.pc] % 100
mode1 = self.mem[self.pc] // 100 % 10
mode2 = self.mem[self.pc] // 1000 % 10
if opcode == 1:
arg1 = self.mem[self.pc + 1] if mode1 else self.mem[self.mem[self.pc + 1]]
arg2 = self.mem[self.pc + 2] if mode2 else self.mem[self.mem[self.pc + 2]]
self.mem[self.mem[self.pc + 3]] = arg1 + arg2
self.pc += 4
elif opcode == 2:
arg1 = self.mem[self.pc + 1] if mode1 else self.mem[self.mem[self.pc + 1]]
arg2 = self.mem[self.pc + 2] if mode2 else self.mem[self.mem[self.pc + 2]]
self.mem[self.mem[self.pc + 3]] = arg1 * arg2
self.pc += 4
elif opcode == 3:
if not self.inp:
return
self.mem[self.mem[self.pc + 1]] = self.inp.pop(0)
self.pc += 2
elif opcode == 4:
arg1 = self.mem[self.pc + 1] if mode1 else self.mem[self.mem[self.pc + 1]]
self.out.append(arg1)
self.pc += 2
elif opcode == 5:
arg1 = self.mem[self.pc + 1] if mode1 else self.mem[self.mem[self.pc + 1]]
arg2 = self.mem[self.pc + 2] if mode2 else self.mem[self.mem[self.pc + 2]]
if arg1:
self.pc = arg2
else:
self.pc += 3
elif opcode == 6:
arg1 = self.mem[self.pc + 1] if mode1 else self.mem[self.mem[self.pc + 1]]
arg2 = self.mem[self.pc + 2] if mode2 else self.mem[self.mem[self.pc + 2]]
if not arg1:
self.pc = arg2
else:
self.pc += 3
elif opcode == 7:
arg1 = self.mem[self.pc + 1] if mode1 else self.mem[self.mem[self.pc + 1]]
arg2 = self.mem[self.pc + 2] if mode2 else self.mem[self.mem[self.pc + 2]]
self.mem[self.mem[self.pc + 3]] = int(arg1 < arg2)
self.pc += 4
elif opcode == 8:
arg1 = self.mem[self.pc + 1] if mode1 else self.mem[self.mem[self.pc + 1]]
arg2 = self.mem[self.pc + 2] if mode2 else self.mem[self.mem[self.pc + 2]]
self.mem[self.mem[self.pc + 3]] = int(arg1 == arg2)
self.pc += 4
elif opcode == 99:
self.running = False
return
(*mem,) = map(int, input.split(","))
def test(seq):
out = 0
instances = []
for i in range(5):
instances.append(IntCode(mem[:]))
instances[-1].inp.append(seq[i])
instances[-1].start()
i = 0
while instances[-1].running:
instances[i].inp.append(out)
instances[i].cont()
out = instances[i].out.pop()
i = (i + 1) % 5
return out
print(max(test(seq) for seq in itertools.permutations(range(5, 10))))

View file

@ -1,61 +0,0 @@
import itertools
def intcode(mem, inp):
pc = 0
while pc < len(mem):
opcode = mem[pc] % 100
mode1 = mem[pc] // 100 % 10
mode2 = mem[pc] // 1000 % 10
if opcode == 1:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
mem[mem[pc+3]] = arg1 + arg2
pc += 4
elif opcode == 2:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
mem[mem[pc+3]] = arg1 * arg2
pc += 4
elif opcode == 3:
mem[mem[pc+1]] = inp.pop(0)
pc += 2
elif opcode == 4:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
return arg1
pc += 2
elif opcode == 5:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
if arg1:
pc = arg2
else:
pc += 3
elif opcode == 6:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
if not arg1:
pc = arg2
else:
pc += 3
elif opcode == 7:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
mem[mem[pc+3]] = int(arg1 < arg2)
pc += 4
elif opcode == 8:
arg1 = mem[pc+1] if mode1 else mem[mem[pc+1]]
arg2 = mem[pc+2] if mode2 else mem[mem[pc+2]]
mem[mem[pc+3]] = int(arg1 == arg2)
pc += 4
elif opcode == 99:
break
*mem, = map(int, open("input.txt").read().split(","))
def test(seq):
out = 0
for i in seq:
out = intcode(mem[:], [i, out])
return out
print(max(test(seq) for seq in itertools.permutations(range(5))))

View file

@ -1,85 +0,0 @@
import itertools
class IntCode:
def __init__(self, mem):
self.mem = mem
self.pc = 0
self.running = False
self.inp = []
self.out = []
def start(self):
self.running = True
self.cont()
def cont(self):
while self.pc < len(self.mem):
opcode = self.mem[self.pc] % 100
mode1 = self.mem[self.pc] // 100 % 10
mode2 = self.mem[self.pc] // 1000 % 10
if opcode == 1:
arg1 = self.mem[self.pc+1] if mode1 else self.mem[self.mem[self.pc+1]]
arg2 = self.mem[self.pc+2] if mode2 else self.mem[self.mem[self.pc+2]]
self.mem[self.mem[self.pc+3]] = arg1 + arg2
self.pc += 4
elif opcode == 2:
arg1 = self.mem[self.pc+1] if mode1 else self.mem[self.mem[self.pc+1]]
arg2 = self.mem[self.pc+2] if mode2 else self.mem[self.mem[self.pc+2]]
self.mem[self.mem[self.pc+3]] = arg1 * arg2
self.pc += 4
elif opcode == 3:
if not self.inp:
return
self.mem[self.mem[self.pc+1]] = self.inp.pop(0)
self.pc += 2
elif opcode == 4:
arg1 = self.mem[self.pc+1] if mode1 else self.mem[self.mem[self.pc+1]]
self.out.append(arg1)
self.pc += 2
elif opcode == 5:
arg1 = self.mem[self.pc+1] if mode1 else self.mem[self.mem[self.pc+1]]
arg2 = self.mem[self.pc+2] if mode2 else self.mem[self.mem[self.pc+2]]
if arg1:
self.pc = arg2
else:
self.pc += 3
elif opcode == 6:
arg1 = self.mem[self.pc+1] if mode1 else self.mem[self.mem[self.pc+1]]
arg2 = self.mem[self.pc+2] if mode2 else self.mem[self.mem[self.pc+2]]
if not arg1:
self.pc = arg2
else:
self.pc += 3
elif opcode == 7:
arg1 = self.mem[self.pc+1] if mode1 else self.mem[self.mem[self.pc+1]]
arg2 = self.mem[self.pc+2] if mode2 else self.mem[self.mem[self.pc+2]]
self.mem[self.mem[self.pc+3]] = int(arg1 < arg2)
self.pc += 4
elif opcode == 8:
arg1 = self.mem[self.pc+1] if mode1 else self.mem[self.mem[self.pc+1]]
arg2 = self.mem[self.pc+2] if mode2 else self.mem[self.mem[self.pc+2]]
self.mem[self.mem[self.pc+3]] = int(arg1 == arg2)
self.pc += 4
elif opcode == 99:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
def test(seq):
out = 0
instances = []
for i in range(5):
instances.append(IntCode(mem[:]))
instances[-1].inp.append(seq[i])
instances[-1].start()
i = 0
while instances[-1].running:
instances[i].inp.append(out)
instances[i].cont()
out = instances[i].out.pop()
i = (i + 1) % 5
return out
print(max(test(seq) for seq in itertools.permutations(range(5, 10))))

53
Python/2019/08.py Normal file
View file

@ -0,0 +1,53 @@
from lib import *
input = read_input(2019, 8)
wid = 25
hei = 6
layers = []
for i, c in enumerate(map(int, input.strip())):
if i % (wid * hei) == 0:
layers.append([])
if i % wid == 0:
layers[-1].append([])
layers[-1][-1].append(c)
def count(layer, digit):
return sum(d == digit for l in layer for d in l)
fewest = wid * hei
out = 0
for layer in layers:
cnt = count(layer, 0)
if cnt < fewest:
fewest = cnt
out = count(layer, 1) * count(layer, 2)
print(out)
wid = 25
hei = 6
layers = []
for i, c in enumerate(map(int, input.strip())):
if i % (wid * hei) == 0:
layers.append([])
if i % wid == 0:
layers[-1].append([])
layers[-1][-1].append(c)
out = []
for i in range(hei):
out.append([])
for j in range(wid):
d = 2
for layer in layers:
if layer[i][j] != 2:
d = layer[i][j]
break
out[-1].append(d)
for l in out:
print("".join(" #"[d] * 2 for d in l))

View file

@ -1,22 +0,0 @@
wid = 25
hei = 6
layers = []
for i, c in enumerate(map(int, open("input.txt").read().strip())):
if i % (wid * hei) == 0:
layers.append([])
if i % wid == 0:
layers[-1].append([])
layers[-1][-1].append(c)
def count(layer, digit):
return sum(d == digit for l in layer for d in l)
fewest = wid * hei
out = 0
for layer in layers:
cnt = count(layer, 0)
if cnt < fewest:
fewest = cnt
out = count(layer, 1) * count(layer, 2)
print(out)

View file

@ -1,23 +0,0 @@
wid = 25
hei = 6
layers = []
for i, c in enumerate(map(int, open("input.txt").read().strip())):
if i % (wid * hei) == 0:
layers.append([])
if i % wid == 0:
layers[-1].append([])
layers[-1][-1].append(c)
out = []
for i in range(hei):
out.append([])
for j in range(wid):
d = 2
for layer in layers:
if layer[i][j] != 2:
d = layer[i][j]
break
out[-1].append(d)
for l in out:
print("".join(" #"[d]*2 for d in l))

View file

@ -1,3 +1,8 @@
from lib import *
input = read_input(2019, 9)
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
@ -10,18 +15,18 @@ class IntCode:
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem[out]
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
@ -31,7 +36,7 @@ class IntCode:
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
@ -69,7 +74,15 @@ class IntCode:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
(*mem,) = map(int, input.split(","))
intcode = IntCode(mem)
intcode.inp.append(1)
intcode.start()
print(*intcode.out)
(*mem,) = map(int, input.split(","))
intcode = IntCode(mem)
intcode.inp.append(2)
intcode.start()

View file

@ -1,76 +0,0 @@
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
self.pc = 0
self.running = False
self.inp = []
self.out = []
self.rel = 0
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem[out]
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
pos += self.rel
self.mem[pos] = value
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
elif opcode == 2:
self.write_arg(3, self.get_arg(1) * self.get_arg(2))
self.pc += 4
elif opcode == 3:
if not self.inp:
return
self.write_arg(1, self.inp.pop(0))
self.pc += 2
elif opcode == 4:
self.out.append(self.get_arg(1))
self.pc += 2
elif opcode == 5:
if self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 6:
if not self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 7:
self.write_arg(3, int(self.get_arg(1) < self.get_arg(2)))
self.pc += 4
elif opcode == 8:
self.write_arg(3, int(self.get_arg(1) == self.get_arg(2)))
self.pc += 4
elif opcode == 9:
self.rel += self.get_arg(1)
self.pc += 2
elif opcode == 99:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
intcode = IntCode(mem)
intcode.inp.append(1)
intcode.start()
print(*intcode.out)

View file

@ -1,16 +1,16 @@
from math import gcd, atan, pi
from lib import *
*grid, = map(list, open("input.txt").read().splitlines())
input = read_input(2019, 10)
grid = input.splitlines()
height = len(grid)
width = len(grid[0])
assert all(width == len(l) for l in grid)
def calc_angle(x, y):
if not x:
return 0
return atan(y / x) * pi / 180 + 90
def check(x, y, x2, y2):
steps = gcd(abs(x2 - x), abs(y2 - y))
steps = math.gcd(abs(x2 - x), abs(y2 - y))
xstep = (x2 - x) // steps
ystep = (y2 - y) // steps
for _ in range(steps - 1):
@ -20,6 +20,7 @@ def check(x, y, x2, y2):
return False
return True
def count(x, y):
out = 0
for y2 in range(height):
@ -28,6 +29,41 @@ def count(x, y):
out += 1
return out
print(max(count(x, y) for y in range(height) for x in range(width) if grid[y][x] == "#"))
(*grid,) = map(list, input.splitlines())
height = len(grid)
width = len(grid[0])
def calc_angle(x, y):
if not x:
return 0
return math.atan(y / x) * math.pi / 180 + 90
def check(x, y, x2, y2):
steps = math.gcd(abs(x2 - x), abs(y2 - y))
xstep = (x2 - x) // steps
ystep = (y2 - y) // steps
for _ in range(steps - 1):
x += xstep
y += ystep
if grid[y][x] == "#":
return False
return True
def count(x, y):
out = 0
for y2 in range(height):
for x2 in range(width):
if (x != x2 or y != y2) and grid[y2][x2] == "#" and check(x, y, x2, y2):
out += 1
return out
asteroids = [(x, y) for y in range(height) for x in range(width) if grid[y][x] == "#"]
lx, ly = max(asteroids, key=lambda a: count(*a))
asteroids.remove((lx, ly))

View file

@ -1,27 +0,0 @@
from math import gcd
grid = open("input.txt").read().splitlines()
height = len(grid)
width = len(grid[0])
assert all(width == len(l) for l in grid)
def check(x, y, x2, y2):
steps = gcd(abs(x2 - x), abs(y2 - y))
xstep = (x2 - x) // steps
ystep = (y2 - y) // steps
for _ in range(steps - 1):
x += xstep
y += ystep
if grid[y][x] == "#":
return False
return True
def count(x, y):
out = 0
for y2 in range(height):
for x2 in range(width):
if (x != x2 or y != y2) and grid[y2][x2] == "#" and check(x, y, x2, y2):
out += 1
return out
print(max(count(x, y) for y in range(height) for x in range(width) if grid[y][x] == "#"))

View file

@ -1,3 +1,8 @@
from lib import *
input = read_input(2019, 11)
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
@ -10,18 +15,18 @@ class IntCode:
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
@ -31,7 +36,7 @@ class IntCode:
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
@ -69,7 +74,28 @@ class IntCode:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
(*mem,) = map(int, input.split(","))
intcode = IntCode(mem)
intcode.start()
o = {}
x = y = 0
dx = 0
dy = -1
while intcode.running:
intcode.inp.append(o.get((x, y), 0))
intcode.cont()
o[(x, y)] = intcode.out.pop(0)
if intcode.out.pop(0):
dx, dy = -dy, dx
else:
dx, dy = dy, -dx
x += dx
y += dy
print(len(o))
(*mem,) = map(int, input.split(","))
intcode = IntCode(mem)
intcode.start()
o = {(0, 0): 1}
@ -92,4 +118,4 @@ while intcode.running:
x += dx
y += dy
for y in range(miny, maxy + 1):
print("".join(2*" #"[o.get((x, y), 0)] for x in range(minx, maxx + 1)))
print("".join(2 * " #"[o.get((x, y), 0)] for x in range(minx, maxx + 1)))

View file

@ -1,89 +0,0 @@
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
self.pc = 0
self.running = False
self.inp = []
self.out = []
self.rel = 0
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
pos += self.rel
self.mem[pos] = value
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
elif opcode == 2:
self.write_arg(3, self.get_arg(1) * self.get_arg(2))
self.pc += 4
elif opcode == 3:
if not self.inp:
return
self.write_arg(1, self.inp.pop(0))
self.pc += 2
elif opcode == 4:
self.out.append(self.get_arg(1))
self.pc += 2
elif opcode == 5:
if self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 6:
if not self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 7:
self.write_arg(3, int(self.get_arg(1) < self.get_arg(2)))
self.pc += 4
elif opcode == 8:
self.write_arg(3, int(self.get_arg(1) == self.get_arg(2)))
self.pc += 4
elif opcode == 9:
self.rel += self.get_arg(1)
self.pc += 2
elif opcode == 99:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
intcode = IntCode(mem)
intcode.start()
o = {}
x = y = 0
dx = 0
dy = -1
while intcode.running:
intcode.inp.append(o.get((x, y), 0))
intcode.cont()
o[(x, y)] = intcode.out.pop(0)
if intcode.out.pop(0):
dx, dy = -dy, dx
else:
dx, dy = dy, -dx
x += dx
y += dy
print(len(o))

View file

@ -1,14 +1,36 @@
import math
import re
from lib import *
input = read_input(2019, 12)
moons = []
for line in open("input.txt").read().splitlines():
for line in input.splitlines():
x, y, z = map(int, re.match(r"^<x=([\-\d]+), y=([\-\d]+), z=([\-\d]+)>$", line).groups())
moons.append(([x, y, z], [0, 0, 0]))
for _ in range(1000):
for pos, vel in moons:
for p2, _ in moons:
for i in range(3):
if pos[i] < p2[i]:
vel[i] += 1
elif pos[i] > p2[i]:
vel[i] -= 1
for pos, vel in moons:
for i in range(3):
pos[i] += vel[i]
print(sum(sum(map(abs, pos)) * sum(map(abs, vel)) for pos, vel in moons))
moons = []
for line in input.splitlines():
x, y, z = map(int, re.match(r"^<x=([\-\d]+), y=([\-\d]+), z=([\-\d]+)>$", line).groups())
moons.append(([x, y, z], [0, 0, 0]))
def make_state(dim):
return tuple(e[dim] for moon in moons for e in moon)
def simulate_dimension(dim):
history = {}
time = 0
@ -28,6 +50,7 @@ def simulate_dimension(dim):
for pos, vel in moons:
pos[dim] += vel[dim]
x, y, z = map(simulate_dimension, range(3))
out = x * y // math.gcd(x, y)
out = out * z // math.gcd(out, z)

View file

@ -1,19 +0,0 @@
import re
moons = []
for line in open("input.txt").read().splitlines():
x, y, z = map(int, re.match(r"^<x=([\-\d]+), y=([\-\d]+), z=([\-\d]+)>$", line).groups())
moons.append(([x, y, z], [0, 0, 0]))
for _ in range(1000):
for pos, vel in moons:
for p2, _ in moons:
for i in range(3):
if pos[i] < p2[i]:
vel[i] += 1
elif pos[i] > p2[i]:
vel[i] -= 1
for pos, vel in moons:
for i in range(3):
pos[i] += vel[i]
print(sum(sum(map(abs, pos)) * sum(map(abs, vel)) for pos, vel in moons))

View file

@ -1,3 +1,8 @@
from lib import *
input = read_input(2019, 13)
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
@ -10,18 +15,18 @@ class IntCode:
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
@ -31,7 +36,7 @@ class IntCode:
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
@ -69,7 +74,19 @@ class IntCode:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
(*mem,) = map(int, input.split(","))
intcode = IntCode(mem)
intcode.start()
blocks = 0
while intcode.out:
_, _, t = intcode.out[:3]
del intcode.out[:3]
blocks += t == 2
print(blocks)
(*mem,) = map(int, input.split(","))
mem[0] = 2
intcode = IntCode(mem)
intcode.start()

View file

@ -1,80 +0,0 @@
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
self.pc = 0
self.running = False
self.inp = []
self.out = []
self.rel = 0
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
pos += self.rel
self.mem[pos] = value
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
elif opcode == 2:
self.write_arg(3, self.get_arg(1) * self.get_arg(2))
self.pc += 4
elif opcode == 3:
if not self.inp:
return
self.write_arg(1, self.inp.pop(0))
self.pc += 2
elif opcode == 4:
self.out.append(self.get_arg(1))
self.pc += 2
elif opcode == 5:
if self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 6:
if not self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 7:
self.write_arg(3, int(self.get_arg(1) < self.get_arg(2)))
self.pc += 4
elif opcode == 8:
self.write_arg(3, int(self.get_arg(1) == self.get_arg(2)))
self.pc += 4
elif opcode == 9:
self.rel += self.get_arg(1)
self.pc += 2
elif opcode == 99:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
intcode = IntCode(mem)
intcode.start()
blocks = 0
while intcode.out:
_, _, t = intcode.out[:3]
del intcode.out[:3]
blocks += t == 2
print(blocks)

View file

@ -1,14 +1,54 @@
from lib import *
input = read_input(2019, 14)
def ceil(a, b):
return a // b + (a % b > 0)
reactions = {}
for line in open("input.txt").read().splitlines():
for line in input.splitlines():
reactants, product = line.split(" => ")
reactants = [reactant.split() for reactant in reactants.split(", ")]
amount, product = product.split()
assert product not in reactions
reactions[product] = ([(reactant, int(amount)) for amount, reactant in reactants], int(amount))
ore_used = 0
chemicals = {}
Q = [("FUEL", 1)]
while Q:
chemical, prod_amount = Q.pop(0)
if chemical == "ORE":
ore_used += prod_amount
continue
chem_amount = chemicals.get(chemical, 0)
reaction_amount = prod_amount - chem_amount
if reaction_amount <= 0:
chemicals[chemical] -= prod_amount
continue
reactants, product_amount = reactions[chemical]
reaction_count = ceil(reaction_amount, product_amount)
for reactant, amount in reactants:
Q.append((reactant, amount * reaction_count))
chemicals[chemical] = chem_amount + reaction_count * product_amount - prod_amount
print(ore_used)
def ceil(a, b):
return a // b + (a % b > 0)
reactions = {}
for line in input.splitlines():
reactants, product = line.split(" => ")
reactants = [reactant.split() for reactant in reactants.split(", ")]
amount, product = product.split()
assert product not in reactions
reactions[product] = ([(reactant, int(amount)) for amount, reactant in reactants], int(amount))
def get_ore_used(amount):
ore_used = 0
chemicals = {}
@ -30,6 +70,7 @@ def get_ore_used(amount):
chemicals[chemical] = chem_amount + reaction_count * product_amount - prod_amount
return ore_used
LIMIT = 1000000000000
low = 0
high = LIMIT

View file

@ -1,30 +0,0 @@
def ceil(a, b):
return a // b + (a % b > 0)
reactions = {}
for line in open("input.txt").read().splitlines():
reactants, product = line.split(" => ")
reactants = [reactant.split() for reactant in reactants.split(", ")]
amount, product = product.split()
assert product not in reactions
reactions[product] = ([(reactant, int(amount)) for amount, reactant in reactants], int(amount))
ore_used = 0
chemicals = {}
Q = [("FUEL", 1)]
while Q:
chemical, prod_amount = Q.pop(0)
if chemical == "ORE":
ore_used += prod_amount
continue
chem_amount = chemicals.get(chemical, 0)
reaction_amount = prod_amount - chem_amount
if reaction_amount <= 0:
chemicals[chemical] -= prod_amount
continue
reactants, product_amount = reactions[chemical]
reaction_count = ceil(reaction_amount, product_amount)
for reactant, amount in reactants:
Q.append((reactant, amount * reaction_count))
chemicals[chemical] = chem_amount + reaction_count * product_amount - prod_amount
print(ore_used)

View file

@ -1,4 +1,7 @@
import heapq
from lib import *
input = read_input(2019, 15)
class IntCode:
def __init__(self, mem):
@ -12,18 +15,18 @@ class IntCode:
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
@ -33,7 +36,7 @@ class IntCode:
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
@ -71,6 +74,66 @@ class IntCode:
self.running = False
return
NORTH, SOUTH, WEST, EAST = range(1, 5)
DIRECTIONS = [(0, -1), (0, 1), (-1, 0), (1, 0)]
BACK = {NORTH: SOUTH, SOUTH: NORTH, WEST: EAST, EAST: WEST}
HIT_WALL, MOVED, REACHED_GOAL = range(3)
UNKNOWN, EMPTY, WALL, GOAL = range(4)
grid = {(0, 0): EMPTY}
def get(x, y):
return grid.get((x, y), 0)
def put(x, y, v):
grid[(x, y)] = v
def explore(x, y):
for direction, (dx, dy) in enumerate(DIRECTIONS):
if get(x + dx, y + dy):
continue
intcode.inp.append(direction + 1)
intcode.cont()
result = intcode.out.pop(0)
if result == HIT_WALL:
put(x + dx, y + dy, WALL)
continue
elif result == MOVED:
put(x + dx, y + dy, EMPTY)
elif result == REACHED_GOAL:
put(x + dx, y + dy, GOAL)
explore(x + dx, y + dy)
intcode.inp.append(BACK[direction + 1])
intcode.cont()
intcode.out.pop(0)
(*mem,) = map(int, input.split(","))
intcode = IntCode(mem)
intcode.start()
explore(0, 0)
Q = [(0, 0, 0)]
visited = set()
while Q:
d, x, y = heapq.heappop(Q)
if (x, y) in visited:
continue
visited.add((x, y))
if get(x, y) == GOAL:
print(d)
break
for dx, dy in DIRECTIONS:
if get(x + dx, y + dy) != WALL:
heapq.heappush(Q, (d + 1, x + dx, y + dy))
NORTH, SOUTH, WEST, EAST = range(1, 5)
DIRECTIONS = [(0, -1), (0, 1), (-1, 0), (1, 0)]
BACK = {NORTH: SOUTH, SOUTH: NORTH, WEST: EAST, EAST: WEST}
@ -79,36 +142,40 @@ UNKNOWN, EMPTY, WALL, GOAL = range(4)
grid = {(0, 0): EMPTY}
goal = None
def get(x, y):
return grid.get((x, y), 0)
def put(x, y, v):
global goal
if v == GOAL:
goal = x, y
grid[(x, y)] = v
def explore(x, y):
for direction, (dx, dy) in enumerate(DIRECTIONS):
if get(x+dx, y+dy):
if get(x + dx, y + dy):
continue
intcode.inp.append(direction + 1)
intcode.cont()
result = intcode.out.pop(0)
if result == HIT_WALL:
put(x+dx, y+dy, WALL)
put(x + dx, y + dy, WALL)
continue
elif result == MOVED:
put(x+dx, y+dy, EMPTY)
put(x + dx, y + dy, EMPTY)
elif result == REACHED_GOAL:
put(x+dx, y+dy, GOAL)
explore(x+dx, y+dy)
put(x + dx, y + dy, GOAL)
explore(x + dx, y + dy)
intcode.inp.append(BACK[direction + 1])
intcode.cont()
intcode.out.pop(0)
*mem, = map(int, open("input.txt").read().split(","))
(*mem,) = map(int, input.split(","))
intcode = IntCode(mem)
intcode.start()
explore(0, 0)
@ -118,7 +185,7 @@ visited = set()
max_dist = 0
while Q:
d, x, y = heapq.heappop(Q)
if (x, y) in visited:
continue
visited.add((x, y))
@ -126,6 +193,6 @@ while Q:
max_dist = max(d, max_dist)
for dx, dy in DIRECTIONS:
if get(x+dx, y+dy) != WALL:
heapq.heappush(Q, (d + 1, x+dx, y+dy))
if get(x + dx, y + dy) != WALL:
heapq.heappush(Q, (d + 1, x + dx, y + dy))
print(max_dist)

View file

@ -1,127 +0,0 @@
import heapq
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
self.pc = 0
self.running = False
self.inp = []
self.out = []
self.rel = 0
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
pos += self.rel
self.mem[pos] = value
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
elif opcode == 2:
self.write_arg(3, self.get_arg(1) * self.get_arg(2))
self.pc += 4
elif opcode == 3:
if not self.inp:
return
self.write_arg(1, self.inp.pop(0))
self.pc += 2
elif opcode == 4:
self.out.append(self.get_arg(1))
self.pc += 2
elif opcode == 5:
if self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 6:
if not self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 7:
self.write_arg(3, int(self.get_arg(1) < self.get_arg(2)))
self.pc += 4
elif opcode == 8:
self.write_arg(3, int(self.get_arg(1) == self.get_arg(2)))
self.pc += 4
elif opcode == 9:
self.rel += self.get_arg(1)
self.pc += 2
elif opcode == 99:
self.running = False
return
NORTH, SOUTH, WEST, EAST = range(1, 5)
DIRECTIONS = [(0, -1), (0, 1), (-1, 0), (1, 0)]
BACK = {NORTH: SOUTH, SOUTH: NORTH, WEST: EAST, EAST: WEST}
HIT_WALL, MOVED, REACHED_GOAL = range(3)
UNKNOWN, EMPTY, WALL, GOAL = range(4)
grid = {(0, 0): EMPTY}
def get(x, y):
return grid.get((x, y), 0)
def put(x, y, v):
grid[(x, y)] = v
def explore(x, y):
for direction, (dx, dy) in enumerate(DIRECTIONS):
if get(x+dx, y+dy):
continue
intcode.inp.append(direction + 1)
intcode.cont()
result = intcode.out.pop(0)
if result == HIT_WALL:
put(x+dx, y+dy, WALL)
continue
elif result == MOVED:
put(x+dx, y+dy, EMPTY)
elif result == REACHED_GOAL:
put(x+dx, y+dy, GOAL)
explore(x+dx, y+dy)
intcode.inp.append(BACK[direction + 1])
intcode.cont()
intcode.out.pop(0)
*mem, = map(int, open("input.txt").read().split(","))
intcode = IntCode(mem)
intcode.start()
explore(0, 0)
Q = [(0, 0, 0)]
visited = set()
while Q:
d, x, y = heapq.heappop(Q)
if (x, y) in visited:
continue
visited.add((x, y))
if get(x, y) == GOAL:
print(d)
break
for dx, dy in DIRECTIONS:
if get(x+dx, y+dy) != WALL:
heapq.heappush(Q, (d + 1, x+dx, y+dy))

View file

@ -1,4 +1,8 @@
*lst, = map(int, open("input.txt").read().strip())
from lib import *
input = read_input(2019, 16)
(*lst,) = map(int, input.strip())
n = len(lst)
for _ in range(100):
@ -24,3 +28,19 @@ for _ in range(100):
lst = out
print("".join(map(str, lst[:8])))
(*lst,) = map(int, input.strip())
offset = int("".join(map(str, lst[:7])))
lst = (lst * 10_000)[: offset - 1 : -1]
n = len(lst)
for _ in range(100):
out = []
s = 0
for i in range(n):
s = (s + lst[i]) % 10
out.append(s)
lst = out
print("".join(map(str, lst[:-9:-1])))

View file

@ -1,15 +0,0 @@
*lst, = map(int, open("input.txt").read().strip())
offset = int("".join(map(str, lst[:7])))
lst = (lst * 10_000)[:offset-1:-1]
n = len(lst)
for _ in range(100):
out = []
s = 0
for i in range(n):
s = (s + lst[i]) % 10
out.append(s)
lst = out
print("".join(map(str, lst[:-9:-1])))

View file

@ -1,3 +1,8 @@
from lib import *
input = read_input(2019, 17)
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
@ -10,18 +15,18 @@ class IntCode:
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
@ -31,7 +36,7 @@ class IntCode:
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
@ -69,19 +74,37 @@ class IntCode:
self.running = False
return
(*mem,) = map(int, input.split(","))
intcode = IntCode(mem)
intcode.start()
grid = "".join(map(chr, intcode.out)).strip().splitlines()
out = 0
for i in range(1, len(grid) - 1):
for j in range(1, len(grid[i]) - 1):
if grid[i][j] == grid[i][j - 1] == grid[i][j + 1] == grid[i - 1][j] == grid[i + 1][j] == "#":
out += i * j
print(out)
def apply_direction(x, y, d):
d %= 4
if d == 0: y -= 1
elif d == 2: y += 1
elif d == 1: x += 1
elif d == 3: x -= 1
if d == 0:
y -= 1
elif d == 2:
y += 1
elif d == 1:
x += 1
elif d == 3:
x -= 1
return x, y
def is_path(x, y):
return y in range(len(grid)) and x in range(len(grid[y])) and grid[y][x] == "#"
*mem, = map(int, open("input.txt").read().split(","))
(*mem,) = map(int, input.split(","))
mem[0] = 2
intcode = IntCode(mem)
intcode.start()
@ -114,6 +137,7 @@ while True:
if cnt:
instructions.append(inst + "," + str(cnt))
def get_groups(start, groups):
if start >= len(instructions):
return groups
@ -131,12 +155,13 @@ def get_groups(start, groups):
if result:
return result
groups = get_groups(0, [None, None, None])
main = []
i = 0
while i < len(instructions):
for j, g in enumerate(groups):
if g == instructions[i:i+len(g)]:
if g == instructions[i : i + len(g)]:
main.append("ABC"[j])
i += len(g)
break

View file

@ -1,81 +0,0 @@
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
self.pc = 0
self.running = False
self.inp = []
self.out = []
self.rel = 0
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
pos += self.rel
self.mem[pos] = value
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
elif opcode == 2:
self.write_arg(3, self.get_arg(1) * self.get_arg(2))
self.pc += 4
elif opcode == 3:
if not self.inp:
return
self.write_arg(1, self.inp.pop(0))
self.pc += 2
elif opcode == 4:
self.out.append(self.get_arg(1))
self.pc += 2
elif opcode == 5:
if self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 6:
if not self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 7:
self.write_arg(3, int(self.get_arg(1) < self.get_arg(2)))
self.pc += 4
elif opcode == 8:
self.write_arg(3, int(self.get_arg(1) == self.get_arg(2)))
self.pc += 4
elif opcode == 9:
self.rel += self.get_arg(1)
self.pc += 2
elif opcode == 99:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
intcode = IntCode(mem)
intcode.start()
grid = "".join(map(chr, intcode.out)).strip().splitlines()
out = 0
for i in range(1, len(grid) - 1):
for j in range(1, len(grid[i]) - 1):
if grid[i][j] == grid[i][j-1] == grid[i][j+1] == grid[i-1][j] == grid[i+1][j] == "#":
out += i * j
print(out)

185
Python/2019/18.py Normal file
View file

@ -0,0 +1,185 @@
from lib import *
input = read_input(2019, 18)
KEY_INDEX = {a: i for i, a in enumerate(string.ascii_lowercase)}
def key_to_num(key):
return 1 << KEY_INDEX[key.lower()]
grid = []
pos = None
key_count = 0
graph = {}
nodes = {}
for i, line in enumerate(input.splitlines()):
for j, c in enumerate(line):
if "a" <= c <= "z":
key_count += 1
graph[c] = {}
nodes[c] = j, i
elif "A" <= c <= "Z":
graph[c] = {}
nodes[c] = j, i
elif c == "@":
pos = j, i
graph[c] = {}
nodes[c] = j, i
grid.append(line)
for src in graph:
Q = [(*nodes[src], 0)]
visited = set()
while Q:
x, y, d = Q.pop(0)
if (x, y) in visited:
continue
visited.add((x, y))
cell = grid[y][x]
if cell != src and cell in graph:
graph[src][cell] = min(d, graph[src].get(cell, 1e1337))
continue
for dx, dy in [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]:
if not (dx in range(len(grid[0])) and dy in range(len(grid))):
continue
if grid[dy][dx] == "#":
continue
Q.append((dx, dy, d + 1))
visited = set()
Q = [(0, "@", 0)]
while Q:
d, p, keys = heapq.heappop(Q)
if (p, keys) in visited:
continue
visited.add((p, keys))
if keys == (1 << key_count) - 1:
print(d)
break
j, i = nodes[p]
cell = grid[i][j]
if "a" <= cell <= "z" and not key_to_num(cell) & keys:
heapq.heappush(Q, (d, p, keys | key_to_num(cell)))
continue
for q, dist in graph[p].items():
if "A" <= q <= "Z" and not key_to_num(q.lower()) & keys:
continue
heapq.heappush(Q, (d + dist, q, keys))
grid = []
pos = None
key_count = 0
graph = {str(i): {} for i in range(4)}
nodes = {str(i): None for i in range(4)}
for i, line in enumerate(input.splitlines()):
line = list(line)
for j, c in enumerate(line):
if "a" <= c <= "z":
key_count += 1
graph[c] = {}
nodes[c] = j, i
elif "A" <= c <= "Z":
graph[c] = {}
nodes[c] = j, i
elif c == "@":
pos = j, i
graph[c] = {}
nodes[c] = j, i
grid.append(line)
sector_keys = [
set(grid[i][j] for i in range(len(grid) // 2) for j in range(len(grid[0]) // 2) if "a" <= grid[i][j] <= "z"),
set(
grid[i][j]
for i in range(len(grid) // 2)
for j in range(len(grid[0]) // 2, len(grid[0]))
if "a" <= grid[i][j] <= "z"
),
set(
grid[i][j]
for i in range(len(grid) // 2, len(grid))
for j in range(len(grid[0]) // 2)
if "a" <= grid[i][j] <= "z"
),
set(
grid[i][j]
for i in range(len(grid) // 2, len(grid))
for j in range(len(grid[0]) // 2, len(grid[0]))
if "a" <= grid[i][j] <= "z"
),
]
j, i = pos
del graph["@"]
del nodes["@"]
for i, j in [(i, j), (i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
grid[i][j] = "#"
j, i = pos
grid[i - 1][j - 1] = "0"
grid[i - 1][j + 1] = "1"
grid[i + 1][j - 1] = "2"
grid[i + 1][j + 1] = "3"
nodes["0"] = j - 1, i - 1
nodes["1"] = j + 1, i - 1
nodes["2"] = j - 1, i + 1
nodes["3"] = j + 1, i + 1
for src in graph:
Q = [(*nodes[src], 0)]
visited = set()
while Q:
x, y, d = Q.pop(0)
if (x, y) in visited:
continue
visited.add((x, y))
cell = grid[y][x]
if cell != src and cell in graph:
graph[src][cell] = min(d, graph[src].get(cell, 1e1337))
continue
for dx, dy in [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]:
if not (dx in range(len(grid[0])) and dy in range(len(grid))):
continue
if grid[dy][dx] == "#":
continue
Q.append((dx, dy, d + 1))
out = 0
for robot in range(4):
visited = set()
Q = [(0, str(robot), 0)]
while Q:
d, p, keys = heapq.heappop(Q)
if (p, keys) in visited:
continue
visited.add((p, keys))
if keys == sum(key_to_num(ek) for ek in sector_keys[robot]):
out += d
break
j, i = nodes[p]
cell = grid[i][j]
if "a" <= cell <= "z" and not key_to_num(cell) & keys:
heapq.heappush(Q, (d, p, keys | key_to_num(cell)))
continue
for q, dist in graph[p].items():
if "A" <= q <= "Z" and not key_to_num(q.lower()) & keys and q in sector_keys[robot]:
continue
heapq.heappush(Q, (d + dist, q, keys))
print(out)

View file

@ -1,72 +0,0 @@
from string import ascii_lowercase as letters
import heapq
KEY_INDEX = {a: i for i, a in enumerate(letters)}
def key_to_num(key):
return 1 << KEY_INDEX[key.lower()]
grid = []
pos = None
key_count = 0
graph = {}
nodes = {}
for i, line in enumerate(open("input.txt").read().splitlines()):
for j, c in enumerate(line):
if "a" <= c <= "z":
key_count += 1
graph[c] = {}
nodes[c] = j, i
elif "A" <= c <= "Z":
graph[c] = {}
nodes[c] = j, i
elif c == "@":
pos = j, i
graph[c] = {}
nodes[c] = j, i
grid.append(line)
for src in graph:
Q = [(*nodes[src], 0)]
visited = set()
while Q:
x, y, d = Q.pop(0)
if (x, y) in visited:
continue
visited.add((x, y))
cell = grid[y][x]
if cell != src and cell in graph:
graph[src][cell] = min(d, graph[src].get(cell, 1e1337))
continue
for dx, dy in [(x-1,y), (x+1,y), (x,y-1), (x,y+1)]:
if not (dx in range(len(grid[0])) and dy in range(len(grid))):
continue
if grid[dy][dx] == "#":
continue
Q.append((dx, dy, d + 1))
visited = set()
Q = [(0, "@", 0)]
while Q:
d, p, keys = heapq.heappop(Q)
if (p, keys) in visited:
continue
visited.add((p, keys))
if keys == (1<<key_count) - 1:
print(d)
break
j, i = nodes[p]
cell = grid[i][j]
if "a" <= cell <= "z" and not key_to_num(cell) & keys:
heapq.heappush(Q, (d, p, keys | key_to_num(cell)))
continue
for q, dist in graph[p].items():
if "A" <= q <= "Z" and not key_to_num(q.lower()) & keys:
continue
heapq.heappush(Q, (d + dist, q, keys))

View file

@ -1,98 +0,0 @@
from string import ascii_lowercase as letters
import heapq
KEY_INDEX = {a: i for i, a in enumerate(letters)}
def key_to_num(key):
return 1 << KEY_INDEX[key.lower()]
grid = []
pos = None
key_count = 0
graph = {str(i): {} for i in range(4)}
nodes = {str(i): None for i in range(4)}
for i, line in enumerate(open("input.txt").read().splitlines()):
line = list(line)
for j, c in enumerate(line):
if "a" <= c <= "z":
key_count += 1
graph[c] = {}
nodes[c] = j, i
elif "A" <= c <= "Z":
graph[c] = {}
nodes[c] = j, i
elif c == "@":
pos = j, i
graph[c] = {}
nodes[c] = j, i
grid.append(line)
sector_keys = [
set(grid[i][j] for i in range(len(grid) // 2) for j in range(len(grid[0]) // 2) if "a" <= grid[i][j] <= "z"),
set(grid[i][j] for i in range(len(grid) // 2) for j in range(len(grid[0]) // 2, len(grid[0])) if "a" <= grid[i][j] <= "z"),
set(grid[i][j] for i in range(len(grid) // 2, len(grid)) for j in range(len(grid[0]) // 2) if "a" <= grid[i][j] <= "z"),
set(grid[i][j] for i in range(len(grid) // 2, len(grid)) for j in range(len(grid[0]) // 2, len(grid[0])) if "a" <= grid[i][j] <= "z")
]
j, i = pos
del graph["@"]
del nodes["@"]
for i, j in [(i, j), (i-1, j), (i+1, j), (i, j-1), (i, j+1)]:
grid[i][j] = "#"
j, i = pos
grid[i-1][j-1] = "0"
grid[i-1][j+1] = "1"
grid[i+1][j-1] = "2"
grid[i+1][j+1] = "3"
nodes["0"] = j-1, i-1
nodes["1"] = j+1, i-1
nodes["2"] = j-1, i+1
nodes["3"] = j+1, i+1
for src in graph:
Q = [(*nodes[src], 0)]
visited = set()
while Q:
x, y, d = Q.pop(0)
if (x, y) in visited:
continue
visited.add((x, y))
cell = grid[y][x]
if cell != src and cell in graph:
graph[src][cell] = min(d, graph[src].get(cell, 1e1337))
continue
for dx, dy in [(x-1,y), (x+1,y), (x,y-1), (x,y+1)]:
if not (dx in range(len(grid[0])) and dy in range(len(grid))):
continue
if grid[dy][dx] == "#":
continue
Q.append((dx, dy, d + 1))
out = 0
for robot in range(4):
visited = set()
Q = [(0, str(robot), 0)]
while Q:
d, p, keys = heapq.heappop(Q)
if (p, keys) in visited:
continue
visited.add((p, keys))
if keys == sum(key_to_num(ek) for ek in sector_keys[robot]):
out += d
break
j, i = nodes[p]
cell = grid[i][j]
if "a" <= cell <= "z" and not key_to_num(cell) & keys:
heapq.heappush(Q, (d, p, keys | key_to_num(cell)))
continue
for q, dist in graph[p].items():
if "A" <= q <= "Z" and not key_to_num(q.lower()) & keys and q in sector_keys[robot]:
continue
heapq.heappush(Q, (d + dist, q, keys))
print(out)

View file

@ -1,107 +1,129 @@
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
self.pc = 0
self.running = False
self.inp = []
self.out = []
self.rel = 0
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
pos += self.rel
self.mem[pos] = value
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
elif opcode == 2:
self.write_arg(3, self.get_arg(1) * self.get_arg(2))
self.pc += 4
elif opcode == 3:
if not self.inp:
return
self.write_arg(1, self.inp.pop(0))
self.pc += 2
elif opcode == 4:
self.out.append(self.get_arg(1))
self.pc += 2
elif opcode == 5:
if self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 6:
if not self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 7:
self.write_arg(3, int(self.get_arg(1) < self.get_arg(2)))
self.pc += 4
elif opcode == 8:
self.write_arg(3, int(self.get_arg(1) == self.get_arg(2)))
self.pc += 4
elif opcode == 9:
self.rel += self.get_arg(1)
self.pc += 2
elif opcode == 99:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
dp = {}
def test(x, y):
if (x, y) not in dp:
intcode = IntCode(mem)
intcode.inp += [x, y]
intcode.start()
dp[(x, y)] = intcode.out.pop(0)
return dp[(x, y)]
SIZE = 100
x = 0
y = 0
done = False
while not done:
y += 1
for x in range(y + 1):
if test(x, y - x):
y = y - x
done = True
break
while True:
while not test(x, y):
y += 1
while test(x, y + 1):
y += 1
assert test(x, y)
if y >= SIZE - 1 and test(x + SIZE - 1, y - (SIZE - 1)):
print(x * 10000 + y - (SIZE - 1))
break
x += 1
from lib import *
input = read_input(2019, 19)
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
self.pc = 0
self.running = False
self.inp = []
self.out = []
self.rel = 0
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
pos += self.rel
self.mem[pos] = value
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
elif opcode == 2:
self.write_arg(3, self.get_arg(1) * self.get_arg(2))
self.pc += 4
elif opcode == 3:
if not self.inp:
return
self.write_arg(1, self.inp.pop(0))
self.pc += 2
elif opcode == 4:
self.out.append(self.get_arg(1))
self.pc += 2
elif opcode == 5:
if self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 6:
if not self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 7:
self.write_arg(3, int(self.get_arg(1) < self.get_arg(2)))
self.pc += 4
elif opcode == 8:
self.write_arg(3, int(self.get_arg(1) == self.get_arg(2)))
self.pc += 4
elif opcode == 9:
self.rel += self.get_arg(1)
self.pc += 2
elif opcode == 99:
self.running = False
return
(*mem,) = map(int, input.split(","))
def test(x, y):
intcode = IntCode(mem)
intcode.inp += [x, y]
intcode.start()
return intcode.out.pop(0)
print(sum(test(i, j) for i in range(50) for j in range(50)))
(*mem,) = map(int, input.split(","))
dp = {}
def test(x, y):
if (x, y) not in dp:
intcode = IntCode(mem)
intcode.inp += [x, y]
intcode.start()
dp[(x, y)] = intcode.out.pop(0)
return dp[(x, y)]
SIZE = 100
x = 0
y = 0
done = False
while not done:
y += 1
for x in range(y + 1):
if test(x, y - x):
y = y - x
done = True
break
while True:
while not test(x, y):
y += 1
while test(x, y + 1):
y += 1
assert test(x, y)
if y >= SIZE - 1 and test(x + SIZE - 1, y - (SIZE - 1)):
print(x * 10000 + y - (SIZE - 1))
break
x += 1

View file

@ -1,80 +0,0 @@
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
self.pc = 0
self.running = False
self.inp = []
self.out = []
self.rel = 0
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
pos += self.rel
self.mem[pos] = value
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
elif opcode == 2:
self.write_arg(3, self.get_arg(1) * self.get_arg(2))
self.pc += 4
elif opcode == 3:
if not self.inp:
return
self.write_arg(1, self.inp.pop(0))
self.pc += 2
elif opcode == 4:
self.out.append(self.get_arg(1))
self.pc += 2
elif opcode == 5:
if self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 6:
if not self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 7:
self.write_arg(3, int(self.get_arg(1) < self.get_arg(2)))
self.pc += 4
elif opcode == 8:
self.write_arg(3, int(self.get_arg(1) == self.get_arg(2)))
self.pc += 4
elif opcode == 9:
self.rel += self.get_arg(1)
self.pc += 2
elif opcode == 99:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
def test(x, y):
intcode = IntCode(mem)
intcode.inp += [x, y]
intcode.start()
return intcode.out.pop(0)
print(sum(test(i, j) for i in range(50) for j in range(50)))

103
Python/2019/20.py Normal file
View file

@ -0,0 +1,103 @@
from lib import *
input = read_input(2019, 20)
(*maze,) = map(list, input.splitlines())
hei = len(maze)
wid = len(maze[0])
portals = {}
links = {}
for i in range(2, hei - 2):
for j in range(2, wid - 2):
if maze[i][j] != ".":
continue
if "A" <= maze[i][j - 1] <= "Z":
maze[i][j] = (maze[i][j - 2] + maze[i][j - 1]).lower()
if "A" <= maze[i][j + 1] <= "Z":
maze[i][j] = (maze[i][j + 1] + maze[i][j + 2]).lower()
if "A" <= maze[i - 1][j] <= "Z":
maze[i][j] = (maze[i - 2][j] + maze[i - 1][j]).lower()
if "A" <= maze[i + 1][j] <= "Z":
maze[i][j] = (maze[i + 1][j] + maze[i + 2][j]).lower()
name = maze[i][j]
if name == ".":
continue
if name in portals:
portals[name].append((i, j))
links[portals[name][0]] = portals[name][1]
links[portals[name][1]] = portals[name][0]
else:
portals[name] = [(i, j)]
visited = set()
Q = [(0, *portals["aa"][0])]
while Q:
d, i, j = heapq.heappop(Q)
if (i, j) in visited:
continue
visited.add((i, j))
if maze[i][j] == "zz":
print(d)
break
if (i, j) in links:
heapq.heappush(Q, (d + 1, *links[(i, j)]))
for p, q in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if maze[p][q] == "." or "aa" <= maze[p][q] <= "zz":
heapq.heappush(Q, (d + 1, p, q))
(*maze,) = map(list, input.splitlines())
hei = len(maze)
wid = len(maze[0])
portals = {}
links = {}
for i in range(2, hei - 2):
for j in range(2, wid - 2):
if maze[i][j] != ".":
continue
if "A" <= maze[i][j - 1] <= "Z":
maze[i][j] = (maze[i][j - 2] + maze[i][j - 1]).lower()
if "A" <= maze[i][j + 1] <= "Z":
maze[i][j] = (maze[i][j + 1] + maze[i][j + 2]).lower()
if "A" <= maze[i - 1][j] <= "Z":
maze[i][j] = (maze[i - 2][j] + maze[i - 1][j]).lower()
if "A" <= maze[i + 1][j] <= "Z":
maze[i][j] = (maze[i + 1][j] + maze[i + 2][j]).lower()
name = maze[i][j]
if name == ".":
continue
inner = i not in (2, hei - 3) and j not in (2, wid - 3)
if name in portals:
portals[name].append((i, j))
links[portals[name][0]] = (portals[name][1], 1 - 2 * inner)
links[portals[name][1]] = (portals[name][0], 2 * inner - 1)
else:
portals[name] = [(i, j)]
visited = set()
Q = [(0, *portals["aa"][0], 0)]
while Q:
d, i, j, m = heapq.heappop(Q)
if (i, j, m) in visited:
continue
visited.add((i, j, m))
if maze[i][j] == "zz" and m == 0:
print(d)
break
if (i, j) in links:
link, change = links[(i, j)]
if m + change >= 0:
heapq.heappush(Q, (d + 1, *link, m + change))
for p, q in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if maze[p][q] == "." or "aa" <= maze[p][q] <= "zz":
heapq.heappush(Q, (d + 1, p, q, m))

View file

@ -1,49 +0,0 @@
import heapq
*maze, = map(list, open("input.txt").read().splitlines())
hei = len(maze)
wid = len(maze[0])
portals = {}
links = {}
for i in range(2, hei - 2):
for j in range(2, wid - 2):
if maze[i][j] != ".":
continue
if "A" <= maze[i][j-1] <= "Z":
maze[i][j] = (maze[i][j-2] + maze[i][j-1]).lower()
if "A" <= maze[i][j+1] <= "Z":
maze[i][j] = (maze[i][j+1] + maze[i][j+2]).lower()
if "A" <= maze[i-1][j] <= "Z":
maze[i][j] = (maze[i-2][j] + maze[i-1][j]).lower()
if "A" <= maze[i+1][j] <= "Z":
maze[i][j] = (maze[i+1][j] + maze[i+2][j]).lower()
name = maze[i][j]
if name == ".":
continue
if name in portals:
portals[name].append((i, j))
links[portals[name][0]] = portals[name][1]
links[portals[name][1]] = portals[name][0]
else:
portals[name] = [(i, j)]
visited = set()
Q = [(0, *portals["aa"][0])]
while Q:
d, i, j = heapq.heappop(Q)
if (i, j) in visited:
continue
visited.add((i, j))
if maze[i][j] == "zz":
print(d)
break
if (i, j) in links:
heapq.heappush(Q, (d + 1, *links[(i, j)]))
for p, q in [(i-1,j), (i+1,j), (i,j-1), (i,j+1)]:
if maze[p][q] == "." or "aa" <= maze[p][q] <= "zz":
heapq.heappush(Q, (d + 1, p, q))

View file

@ -1,52 +0,0 @@
import heapq
*maze, = map(list, open("input.txt").read().splitlines())
hei = len(maze)
wid = len(maze[0])
portals = {}
links = {}
for i in range(2, hei - 2):
for j in range(2, wid - 2):
if maze[i][j] != ".":
continue
if "A" <= maze[i][j-1] <= "Z":
maze[i][j] = (maze[i][j-2] + maze[i][j-1]).lower()
if "A" <= maze[i][j+1] <= "Z":
maze[i][j] = (maze[i][j+1] + maze[i][j+2]).lower()
if "A" <= maze[i-1][j] <= "Z":
maze[i][j] = (maze[i-2][j] + maze[i-1][j]).lower()
if "A" <= maze[i+1][j] <= "Z":
maze[i][j] = (maze[i+1][j] + maze[i+2][j]).lower()
name = maze[i][j]
if name == ".":
continue
inner = i not in (2, hei - 3) and j not in (2, wid - 3)
if name in portals:
portals[name].append((i, j))
links[portals[name][0]] = (portals[name][1], 1 - 2 * inner)
links[portals[name][1]] = (portals[name][0], 2 * inner - 1)
else:
portals[name] = [(i, j)]
visited = set()
Q = [(0, *portals["aa"][0], 0)]
while Q:
d, i, j, m = heapq.heappop(Q)
if (i, j, m) in visited:
continue
visited.add((i, j, m))
if maze[i][j] == "zz" and m == 0:
print(d)
break
if (i, j) in links:
link, change = links[(i, j)]
if m + change >= 0:
heapq.heappush(Q, (d + 1, *link, m + change))
for p, q in [(i-1,j), (i+1,j), (i,j-1), (i,j+1)]:
if maze[p][q] == "." or "aa" <= maze[p][q] <= "zz":
heapq.heappush(Q, (d + 1, p, q, m))

View file

@ -1,3 +1,8 @@
from lib import *
input = read_input(2019, 21)
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
@ -10,18 +15,18 @@ class IntCode:
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
@ -31,7 +36,7 @@ class IntCode:
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
@ -69,7 +74,18 @@ class IntCode:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
(*mem,) = map(int, input.split(","))
intcode = IntCode(mem)
intcode.start()
intcode.out.clear()
INSTRUCTIONS = ["NOT A J", "NOT B T", "OR T J", "NOT C T", "OR T J", "AND D J", "WALK"]
intcode.inp += map(ord, "".join(i + "\n" for i in INSTRUCTIONS))
intcode.cont()
print(intcode.out[-1])
(*mem,) = map(int, input.split(","))
intcode = IntCode(mem)
intcode.start()
intcode.out.clear()
@ -86,7 +102,7 @@ INSTRUCTIONS = [
"AND E T",
"OR H T",
"AND T J",
"RUN"
"RUN",
]
intcode.inp += map(ord, "".join(i + "\n" for i in INSTRUCTIONS))
intcode.cont()

View file

@ -1,87 +0,0 @@
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
self.pc = 0
self.running = False
self.inp = []
self.out = []
self.rel = 0
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
pos += self.rel
self.mem[pos] = value
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
elif opcode == 2:
self.write_arg(3, self.get_arg(1) * self.get_arg(2))
self.pc += 4
elif opcode == 3:
if not self.inp:
return
self.write_arg(1, self.inp.pop(0))
self.pc += 2
elif opcode == 4:
self.out.append(self.get_arg(1))
self.pc += 2
elif opcode == 5:
if self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 6:
if not self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 7:
self.write_arg(3, int(self.get_arg(1) < self.get_arg(2)))
self.pc += 4
elif opcode == 8:
self.write_arg(3, int(self.get_arg(1) == self.get_arg(2)))
self.pc += 4
elif opcode == 9:
self.rel += self.get_arg(1)
self.pc += 2
elif opcode == 99:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
intcode = IntCode(mem)
intcode.start()
intcode.out.clear()
INSTRUCTIONS = [
"NOT A J",
"NOT B T",
"OR T J",
"NOT C T",
"OR T J",
"AND D J",
"WALK"
]
intcode.inp += map(ord, "".join(i + "\n" for i in INSTRUCTIONS))
intcode.cont()
print(intcode.out[-1])

View file

@ -1,10 +1,29 @@
import re
from lib import *
input = read_input(2019, 22)
DECK = 10007
pos = 2019
for line in input.splitlines():
reverse = re.match(r"deal into new stack", line)
cut = re.match(r"cut (-?\d+)", line)
increment = re.match(r"deal with increment (\d+)", line)
if reverse:
pos = -pos - 1
elif cut:
pos -= int(cut.group(1))
elif increment:
pos *= int(increment.group(1))
pos %= DECK
print(pos)
DECK = 119315717514047
REP = 101741582076661
first, inc = 0, 1
instructions = open("input.txt").read().splitlines()
instructions = input.splitlines()
for line in instructions:
reverse = re.match(r"deal into new stack", line)
cut = re.match(r"cut (-?\d+)", line)

View file

@ -1,17 +0,0 @@
import re
DECK = 10007
pos = 2019
for line in open("input.txt").read().splitlines():
reverse = re.match(r"deal into new stack", line)
cut = re.match(r"cut (-?\d+)", line)
increment = re.match(r"deal with increment (\d+)", line)
if reverse:
pos = -pos - 1
elif cut:
pos -= int(cut.group(1))
elif increment:
pos *= int(increment.group(1))
pos %= DECK
print(pos)

View file

@ -1,3 +1,8 @@
from lib import *
input = read_input(2019, 23)
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
@ -10,18 +15,18 @@ class IntCode:
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
@ -31,7 +36,7 @@ class IntCode:
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
@ -69,7 +74,25 @@ class IntCode:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
(*mem,) = map(int, input.split(","))
nodes = [IntCode(mem) for _ in range(50)]
for i, node in enumerate(nodes):
node.inp.append(i)
node.start()
while True:
for i, node in enumerate(nodes):
while node.out:
dest, x, y, *node.out = node.out
if dest == 255:
print(y)
exit()
nodes[dest].inp += [x, y]
node.inp.append(-1)
node.cont()
(*mem,) = map(int, input.split(","))
nodes = [IntCode(mem) for _ in range(50)]
nat = None
nat_history = set()

View file

@ -1,86 +0,0 @@
class IntCode:
def __init__(self, mem):
self.mem = {i: e for i, e in enumerate(mem)}
self.pc = 0
self.running = False
self.inp = []
self.out = []
self.rel = 0
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
pos += self.rel
self.mem[pos] = value
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
elif opcode == 2:
self.write_arg(3, self.get_arg(1) * self.get_arg(2))
self.pc += 4
elif opcode == 3:
if not self.inp:
return
self.write_arg(1, self.inp.pop(0))
self.pc += 2
elif opcode == 4:
self.out.append(self.get_arg(1))
self.pc += 2
elif opcode == 5:
if self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 6:
if not self.get_arg(1):
self.pc = self.get_arg(2)
else:
self.pc += 3
elif opcode == 7:
self.write_arg(3, int(self.get_arg(1) < self.get_arg(2)))
self.pc += 4
elif opcode == 8:
self.write_arg(3, int(self.get_arg(1) == self.get_arg(2)))
self.pc += 4
elif opcode == 9:
self.rel += self.get_arg(1)
self.pc += 2
elif opcode == 99:
self.running = False
return
*mem, = map(int, open("input.txt").read().split(","))
nodes = [IntCode(mem) for _ in range(50)]
for i, node in enumerate(nodes):
node.inp.append(i)
node.start()
while True:
for i, node in enumerate(nodes):
while node.out:
dest, x, y, *node.out = node.out
if dest == 255:
print(y)
exit()
nodes[dest].inp += [x, y]
node.inp.append(-1)
node.cont()

92
Python/2019/24.py Normal file
View file

@ -0,0 +1,92 @@
from lib import *
input = read_input(2019, 24)
grid = sum((1 << i * 5 + j) * (c == "#") for i, line in enumerate(input.splitlines()) for j, c in enumerate(line))
def get_adjacent(i, j):
return sum(
grid & (1 << i * 5 + j) > 0
for i, j in [(i, j - 1), (i, j + 1), (i - 1, j), (i + 1, j)]
if i in range(5) and j in range(5)
)
def simulate():
out = 0
for i in range(5):
for j in range(5):
if (grid & (1 << i * 5 + j) > 0 and get_adjacent(i, j) == 1) or (
grid & (1 << i * 5 + j) == 0 and get_adjacent(i, j) in (1, 2)
):
out |= 1 << i * 5 + j
return out
history = set()
while True:
if grid in history:
break
history.add(grid)
grid = simulate()
print(grid)
grid = {0: sum((1 << i * 5 + j) * (c == "#") for i, line in enumerate(input.splitlines()) for j, c in enumerate(line))}
def is_alive(i, j, l):
return grid.get(l, 0) & (1 << i * 5 + j) > 0
def get_adjacent(i, j, l):
if (i, j) == (2, 2):
return 0
out = 0
for x, y in [(j - 1, i), (j + 1, i), (j, i - 1), (j, i + 1)]:
outer = grid.get(l - 1, 0)
layer = grid.get(l, 0)
inner = grid.get(l + 1, 0)
if (x, y) == (2, 2):
for k in range(5):
if i == 1:
out += is_alive(0, k, l + 1)
elif j == 1:
out += is_alive(k, 0, l + 1)
elif i == 3:
out += is_alive(4, k, l + 1)
elif j == 3:
out += is_alive(k, 4, l + 1)
else:
if x == -1:
out += is_alive(2, 1, l - 1)
elif y == -1:
out += is_alive(1, 2, l - 1)
elif x == 5:
out += is_alive(2, 3, l - 1)
elif y == 5:
out += is_alive(3, 2, l - 1)
else:
out += is_alive(y, x, l)
return out
def simulate():
out = {}
for l in range(min(grid) - 1, max(grid) + 2):
lout = 0
for i in range(5):
for j in range(5):
if (is_alive(i, j, l) and get_adjacent(i, j, l) == 1) or (
not is_alive(i, j, l) and get_adjacent(i, j, l) in (1, 2)
):
lout |= 1 << i * 5 + j
if lout:
out[l] = lout
return out
for _ in range(200):
grid = simulate()
print(sum(bin(layer).count("1") for layer in grid.values()))

View file

@ -1,20 +0,0 @@
grid = sum((1<<i*5+j)*(c=="#") for i, line in enumerate(open("input.txt").read().splitlines()) for j, c in enumerate(line))
def get_adjacent(i, j):
return sum(grid&(1<<i*5+j)>0 for i, j in [(i,j-1), (i,j+1), (i-1,j), (i+1,j)] if i in range(5) and j in range(5))
def simulate():
out = 0
for i in range(5):
for j in range(5):
if (grid&(1<<i*5+j)>0 and get_adjacent(i, j) == 1) or (grid&(1<<i*5+j)==0 and get_adjacent(i, j) in (1, 2)):
out |= 1<<i*5+j
return out
history = set()
while True:
if grid in history:
break
history.add(grid)
grid = simulate()
print(grid)

View file

@ -1,42 +0,0 @@
grid = {0: sum((1<<i*5+j)*(c=="#") for i, line in enumerate(open("input.txt").read().splitlines()) for j, c in enumerate(line))}
def is_alive(i, j, l):
return grid.get(l, 0)&(1<<i*5+j) > 0
def get_adjacent(i, j, l):
if (i, j) == (2, 2):
return 0
out = 0
for x, y in [(j-1,i), (j+1,i), (j,i-1), (j,i+1)]:
outer = grid.get(l - 1, 0)
layer = grid.get(l, 0)
inner = grid.get(l + 1, 0)
if (x, y) == (2, 2):
for k in range(5):
if i == 1: out += is_alive(0, k, l + 1)
elif j == 1: out += is_alive(k, 0, l + 1)
elif i == 3: out += is_alive(4, k, l + 1)
elif j == 3: out += is_alive(k, 4, l + 1)
else:
if x == -1: out += is_alive(2, 1, l - 1)
elif y == -1: out += is_alive(1, 2, l - 1)
elif x == 5: out += is_alive(2, 3, l - 1)
elif y == 5: out += is_alive(3, 2, l - 1)
else: out += is_alive(y, x, l)
return out
def simulate():
out = {}
for l in range(min(grid) - 1, max(grid) + 2):
lout = 0
for i in range(5):
for j in range(5):
if (is_alive(i, j, l) and get_adjacent(i, j, l) == 1) or (not is_alive(i, j, l) and get_adjacent(i, j, l) in (1, 2)):
lout |= 1<<i*5+j
if lout:
out[l] = lout
return out
for _ in range(200):
grid = simulate()
print(sum(bin(layer).count("1") for layer in grid.values()))

View file

@ -1,4 +1,7 @@
import re
from lib import *
input = read_input(2019, 25)
class IntCode:
def __init__(self, mem):
@ -12,18 +15,18 @@ class IntCode:
def start(self):
self.running = True
self.cont()
def get_arg(self, i):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
out = self.mem[self.pc + i]
if mode == 1:
return out
elif mode == 2:
out += self.rel
return self.mem.get(out, 0)
def write_arg(self, i, value):
mode = self.mem[self.pc] // (10 ** (i+1)) % 10
mode = self.mem[self.pc] // (10 ** (i + 1)) % 10
pos = self.mem[self.pc + i]
assert mode != 1
if mode == 2:
@ -33,7 +36,7 @@ class IntCode:
def cont(self):
while True:
opcode = self.mem[self.pc] % 100
if opcode == 1:
self.write_arg(3, self.get_arg(1) + self.get_arg(2))
self.pc += 4
@ -80,6 +83,7 @@ class IntCode:
self.inp += map(ord, inp + "\n")
self.cont()
class Bot(IntCode):
def __init__(self, mem):
super().__init__(mem)
@ -100,13 +104,13 @@ class Bot(IntCode):
if match:
self.room = match.group(1)
break
out = out[out.index("Doors here lead:")+1:]
self.directions = [d[2:] for d in out[:out.index("")]]
out = out[out.index("Doors here lead:") + 1 :]
self.directions = [d[2:] for d in out[: out.index("")]]
if "Items here:" not in out:
self.items.clear()
return
out = out[out.index("Items here:")+1:]
self.items = [i[2:] for i in out[:out.index("")]]
out = out[out.index("Items here:") + 1 :]
self.items = [i[2:] for i in out[: out.index("")]]
def move(self, direction):
self.input(direction)
@ -125,29 +129,32 @@ class Bot(IntCode):
out = self.output().split("\n")
if "Items in your inventory:" not in out:
return []
out = out[out.index("Items in your inventory:")+1:]
return [i[2:] for i in out[:out.index("")]]
out = out[out.index("Items in your inventory:") + 1 :]
return [i[2:] for i in out[: out.index("")]]
def test(self, direction):
assert self.room == "Security Checkpoint"
self.input(direction)
orig = out = self.output().split("\n")
out = out[out.index("Doors here lead:")+1:]
out = out[out.index("")+1:]
out = out[out.index("Doors here lead:") + 1 :]
out = out[out.index("") + 1 :]
res = "ejected back" not in out[0]
if res:
print(re.match(r"^.*?(\d+).*$", out[2]).group(1))
return res
BACK = {"north": "south", "south": "north", "east": "west", "west": "east"}
*mem, = map(int, open("input.txt").read().split(","))
(*mem,) = map(int, input.split(","))
bot = Bot(mem)
bot.start()
items = []
maze = {}
def explore(r=None, came_from=None, indent=0):
room = bot.room
if r:
@ -169,8 +176,10 @@ def explore(r=None, came_from=None, indent=0):
explore(room, BACK[direction], indent + 1)
bot.move(BACK[direction])
explore()
def make_path(room, dest, f=None):
if room == dest:
return []
@ -182,9 +191,11 @@ def make_path(room, dest, f=None):
if res is not None:
return [d] + res
for d in make_path(bot.room, "Security Checkpoint"):
bot.move(d)
dire, = maze[bot.room]
(dire,) = maze[bot.room]
def test_combination(i):
for e in bot.inv():
@ -194,6 +205,7 @@ def test_combination(i):
bot.take(e)
return bot.test(dire)
for i in range(1<<len(items)):
for i in range(1 << len(items)):
if test_combination(i):
break

View file

@ -20,6 +20,7 @@ import math
import operator
import re
import statistics
import string
from collections import Counter, deque
from copy import deepcopy
from dataclasses import dataclass