Added day 25 and added repl class to intcode
parent
39381d3d86
commit
a6ac23f5c7
|
@ -0,0 +1,120 @@
|
||||||
|
from intcode import parse, emulator, REPL
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
N = 'north'
|
||||||
|
S = 'south'
|
||||||
|
E = 'east'
|
||||||
|
W = 'west'
|
||||||
|
|
||||||
|
back = {N : S, S : N, W : E, E : W}
|
||||||
|
|
||||||
|
def add_vec(xy, d):
|
||||||
|
x, y = xy
|
||||||
|
if d == N:
|
||||||
|
return (x, y+1)
|
||||||
|
if d == S:
|
||||||
|
return (x, y-1)
|
||||||
|
if d == W:
|
||||||
|
return (x-1, y)
|
||||||
|
if d == E:
|
||||||
|
return (x+1, y)
|
||||||
|
|
||||||
|
class Room:
|
||||||
|
def __init__(self, mssg, path):
|
||||||
|
blocks = mssg.strip().split("\n\n")
|
||||||
|
head_str = blocks[0]
|
||||||
|
door_str = blocks[1]
|
||||||
|
item_str = '\n'.join(blocks[2:])
|
||||||
|
|
||||||
|
self.name = re.findall('=+ ([^=]+) =+', head_str)[0]
|
||||||
|
self.description = re.findall(r'=\n([\s\S]+)', head_str)[-1].rstrip()
|
||||||
|
self.doors = re.findall(r'- (\w+)\n?', door_str)
|
||||||
|
self.items = re.findall(r'- (.+)\n?', item_str)
|
||||||
|
self.path = path
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.name == other.name
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
head = "== {} ==\n{}".format(self.name, self.description)
|
||||||
|
doors = "Doors here lead:\n- {}".format("\n- ".join(self.doors))
|
||||||
|
items = "" if self.items == [] else "\n\nItems here:\n- {}".format("\n- ".join(self.items))
|
||||||
|
path = " -> ".join(self.path)
|
||||||
|
return "{}\n\n{}{}\n{}".format(head, doors, items, path)
|
||||||
|
|
||||||
|
|
||||||
|
def encode(s):
|
||||||
|
return map(ord, s + '\n')
|
||||||
|
|
||||||
|
def decode(lst):
|
||||||
|
return ''.join(map(chr, lst))
|
||||||
|
|
||||||
|
def goto_room(repl, room):
|
||||||
|
for d in room.path:
|
||||||
|
repl.write(d)
|
||||||
|
next(repl)
|
||||||
|
|
||||||
|
def try_item(repl, item):
|
||||||
|
if item in ("infinite loop", "giant electromagnet"):
|
||||||
|
return False
|
||||||
|
repl = repl.copy()
|
||||||
|
repl.write("take " + item)
|
||||||
|
next(repl)
|
||||||
|
try:
|
||||||
|
repl.write('')
|
||||||
|
next(repl)
|
||||||
|
return True
|
||||||
|
except StopIteration:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def map_ship(repl):
|
||||||
|
rooms = []
|
||||||
|
items = []
|
||||||
|
def aux(path):
|
||||||
|
s = next(repl)
|
||||||
|
try:
|
||||||
|
room = Room(s, path)
|
||||||
|
except:
|
||||||
|
return
|
||||||
|
if room in rooms:
|
||||||
|
return
|
||||||
|
rooms.append(room)
|
||||||
|
|
||||||
|
for item in room.items:
|
||||||
|
if not try_item(repl, item):
|
||||||
|
continue
|
||||||
|
repl.write("take " + item)
|
||||||
|
next(repl)
|
||||||
|
items.append(item)
|
||||||
|
|
||||||
|
for d in room.doors:
|
||||||
|
repl.write(d)
|
||||||
|
aux(path + [d])
|
||||||
|
repl.write(back[d])
|
||||||
|
next(repl)
|
||||||
|
aux([])
|
||||||
|
return rooms, items
|
||||||
|
|
||||||
|
def preproc(puzzle_input):
|
||||||
|
prog = parse(puzzle_input)
|
||||||
|
emul = emulator(prog)
|
||||||
|
repl = REPL(emul, decode=decode, encode=encode)
|
||||||
|
|
||||||
|
rooms, items = map_ship(repl)
|
||||||
|
|
||||||
|
checkpoint = list(filter(lambda room : room.name == "Security Checkpoint", rooms))[0]
|
||||||
|
goto_room(repl, checkpoint)
|
||||||
|
return repl
|
||||||
|
|
||||||
|
def partI(repl):
|
||||||
|
for item in ["coin", "mutex", "astronaut ice cream", "dehydrated water"]:
|
||||||
|
repl.write("drop " + item)
|
||||||
|
next(repl)
|
||||||
|
repl.write("north")
|
||||||
|
s = next(repl)
|
||||||
|
return re.findall(r'\d+', s)[0]
|
||||||
|
|
||||||
|
def partII(_):
|
||||||
|
return "No solution"
|
||||||
|
|
52
intcode.py
52
intcode.py
|
@ -44,7 +44,7 @@ class emulator():
|
||||||
Input is fed from an iterator. This iterator is empty by default. Use
|
Input is fed from an iterator. This iterator is empty by default. Use
|
||||||
write/append to add overwrite/append to the input iterator.
|
write/append to add overwrite/append to the input iterator.
|
||||||
"""
|
"""
|
||||||
self.memory = defaultlist(program[:], val_factory = lambda : 0)
|
self.memory = defaultlist(program.copy(), val_factory = lambda : 0)
|
||||||
self.i = 0
|
self.i = 0
|
||||||
self.rel_base = 0
|
self.rel_base = 0
|
||||||
|
|
||||||
|
@ -177,6 +177,56 @@ class emulator():
|
||||||
other.pipe_from(self)
|
other.pipe_from(self)
|
||||||
return other
|
return other
|
||||||
|
|
||||||
|
@format_input_args
|
||||||
|
def copy(self, input_iter_copy):
|
||||||
|
"""
|
||||||
|
Copies emulator instance. The input iterator must be copied and provided
|
||||||
|
by the caller.
|
||||||
|
"""
|
||||||
|
new = emulator(self.memory)
|
||||||
|
new.i = self.i
|
||||||
|
new.rel_base = self.rel_base
|
||||||
|
|
||||||
|
new.input_iter = input_iter_copy
|
||||||
|
return new
|
||||||
|
|
||||||
|
# Repl class -------------------------------------------------------
|
||||||
|
class REPL:
|
||||||
|
"""Read-eval-print loop class."""
|
||||||
|
def __init__(self, emul, decode=list, encode=list):
|
||||||
|
"""Takes an emulator and decode/enocde functions"""
|
||||||
|
self.emul = emul
|
||||||
|
self.encode = encode
|
||||||
|
self.decode = decode
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
"""
|
||||||
|
Iterates over emulator output until WaitForInput is risen or the
|
||||||
|
emulator halts. Returns decoded output.
|
||||||
|
"""
|
||||||
|
out = []
|
||||||
|
try:
|
||||||
|
done = True
|
||||||
|
for o in self.emul:
|
||||||
|
done = False
|
||||||
|
out.append(o)
|
||||||
|
if done:
|
||||||
|
raise StopIteration
|
||||||
|
except WaitForInput:
|
||||||
|
pass
|
||||||
|
return self.decode(out)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def write(self, i):
|
||||||
|
"""Encodes input and writes it to emulator"""
|
||||||
|
self.emul.write_input(input_iter = self.encode(i))
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
"""Copies repl instance."""
|
||||||
|
return REPL(self.emul.copy(), self.decode, self.encode)
|
||||||
|
|
||||||
# Useful functions --------------------------------------------------
|
# Useful functions --------------------------------------------------
|
||||||
|
|
||||||
def parse(s):
|
def parse(s):
|
||||||
|
|
Loading…
Reference in New Issue