diff --git a/day15.py b/day15.py index a973374..9f2c2af 100644 --- a/day15.py +++ b/day15.py @@ -1,3 +1,4 @@ +from collections import deque from intcode import IntCode from tools.aoc import AOCDay from tools.coordinate import Coordinate @@ -6,58 +7,79 @@ from typing import Any MOVEMENTS = [Coordinate(0, -1), Coordinate(0, 1), Coordinate(-1, 0), Coordinate(1, 0)] +OXYGEN_POS = None + + +def discover(comp: IntCode, grid: Grid, pos: Coordinate, visited: set = None) -> Grid: + global OXYGEN_POS + + if visited is None: + visited = set() + + visited.add(pos) + + for m in range(4): + next_pos = pos + MOVEMENTS[m] + if next_pos in visited: + continue + + comp.addInput(m + 1) + outcome = comp.getOutput() + if outcome == 0: + grid.set(next_pos) + else: + if outcome == 2: + OXYGEN_POS = next_pos + grid = discover(comp, grid, next_pos, visited) + comp.addInput(MOVEMENTS.index(MOVEMENTS[m].reverse()) + 1) + comp.getOutput() # just ignore one to keep the queue clear + + return grid class Day(AOCDay): inputs = [ [ - (None, "input15") + (354, "input15") ], [ - (None, "input15") + (370, "input15") ] ] - def part1(self) -> Any: + def get_grid(self) -> Grid: comp = IntCode(self.getInputAsArraySplit(",", int)) comp.start() pos = Coordinate(0, 0) - ox_pos = None - area = Grid() - while ox_pos is None: - madeMove = Coordinate(0, 0) - for i, move in enumerate(MOVEMENTS): - if not area.isSet(pos + move): - print("Trying to move to", pos + move) - comp.addInput(i + 1) - madeMove = move - break - - reply = comp.getOutput() - print("comp replied with", reply) - if reply == 0: - area.set(pos + madeMove) - elif reply == 1: - pos += madeMove - else: - ox_pos = pos + madeMove - - for y in range(area.minY, area.maxY + 1): - for x in range(area.minX, area.maxX + 1): - if area.isSet(Coordinate(x, y)): - print("#", end="") - else: - print(" ", end="") - - print() - - print("Oxygen System found at", ox_pos) + return discover(comp, Grid(), pos) + def part1(self) -> Any: + return len(self.get_grid().getPath(Coordinate(0, 0), OXYGEN_POS, includeDiagonal=False, walls=[True])) - 1 def part2(self) -> Any: - return "" + grid = self.get_grid() + queue = deque() + queue.append(OXYGEN_POS) + grid.set(OXYGEN_POS, 2) + count = 0 + + grid.print(true_char='#', false_char=' ', mark=[Coordinate(0, 0), OXYGEN_POS]) + + while queue: + print("step", count, "=>", queue) + count += 1 + next_queue = deque() + for pos in queue: + for next_pos in grid.getNeighboursOf(pos, includeDefault=True, includeDiagonal=False): + if grid.get(next_pos) is False: + next_queue.append(next_pos) + grid.set(next_pos, 2) + + queue = next_queue + + return count - 1 if __name__ == '__main__': - day = Day(15) + day = Day(2019, 15) day.run(verbose=True) diff --git a/intcode.py b/intcode.py index 10c25b3..63c14a8 100644 --- a/intcode.py +++ b/intcode.py @@ -31,9 +31,11 @@ class IntCode(threading.Thread): self.relative_base = 0 def getMemoryValue(self, address: int) -> int: - return self.memory[address] + return int(self.memory[address]) def setMemoryValue(self, address: int, value: int): + if not isinstance(value, int): + print("Something set", value, "at", address, "and that's not int, but", value.__class__.__name__) self.memory[address] = value def getParameterValue(self, address: int, mode: int = 0) -> int: