Implement brute force for 2019 day 25

This commit is contained in:
2021-10-18 15:51:44 +02:00
parent 71f54bac6b
commit e66f3df949

View File

@@ -1,9 +1,15 @@
from typing import TextIO import itertools
from typing import TextIO, Iterable, Tuple, Set
from aoc2019.intcode import read_program, Computer from aoc2019.intcode import read_program, Computer
def print_output(computer: Computer): def powerset(iterable: Iterable) -> Iterable[Tuple]:
s = list(iterable)
return itertools.chain.from_iterable(itertools.combinations(s, r) for r in range(len(s) + 1))
def print_output(computer: Computer) -> str:
output = "" output = ""
while len(computer.output): while len(computer.output):
@@ -11,6 +17,8 @@ def print_output(computer: Computer):
print(output, end='') print(output, end='')
return output
def load_save(save, computer: Computer): def load_save(save, computer: Computer):
computer.pointer, computer.relative_base, computer.program = save computer.pointer, computer.relative_base, computer.program = save
@@ -20,10 +28,40 @@ def create_save(computer: Computer):
return computer.pointer, computer.relative_base, computer.program.copy() return computer.pointer, computer.relative_base, computer.program.copy()
def send_command(computer: Computer, command: str):
for c in command:
computer.send_input(ord(c))
computer.send_input(10) # manually send newline
def force(computer: Computer, direction: str, items: Set[str]):
for combination in powerset(items):
# Drop everything, disregard what's on the ground
for item in items:
send_command(computer, f"drop {item}")
# Now pick up whatever we want to try
for item in combination:
send_command(computer, f"take {item}")
send_command(computer, direction)
try:
computer.run()
print_output(computer)
return True
except IndexError:
print_output(computer)
return False
def part1(data: TextIO): def part1(data: TextIO):
print("This day must use a file as input as it requires the stdin for other things.") print("This day must use a file as input as it requires the stdin for other things.")
computer = Computer(read_program(data)) computer = Computer(read_program(data))
items = set()
saves = {} saves = {}
@@ -42,14 +80,35 @@ def part1(data: TextIO):
saves['auto'] = create_save(computer) saves['auto'] = create_save(computer)
try:
command = input().strip() command = input().strip()
except EOFError:
return "exiting"
if command == "exit": if command == "exit":
return "exiting"
elif command == "items":
print(items)
continue
elif command.startswith("save "):
save_name = command.removeprefix("save ")
saves[save_name] = create_save(computer)
print(f"Saved game state as {save_name}")
continue
elif command.startswith("load "):
save_name = command.removeprefix("load ")
load_save(saves[save_name], computer)
print(f"Loaded game state from {save_name}")
continue
elif command.startswith("take "):
items.add(command.removeprefix("take "))
elif command.startswith("drop "):
items.remove(command.removeprefix("drop "))
elif command.startswith("force "):
direction = command.removeprefix("force ")
if force(computer, direction, items):
return return
# TODO: add manual save states. continue
for c in command: send_command(computer, command)
computer.send_input(ord(c))
computer.send_input(10) # manually send newline