def neighbors(x: int, y: int) -> Set[Coord]: retVal = [] if x > 0: retVal.append(Coord(x-1, y)) if x < 127: retVal.append(Coord(x+1, y)) if y > 0: retVal.append(Coord(x, y-1)) if y < 127: retVal.append(Coord(x, y+1)) return retVal
def part1(inp: Set[Coord], cycles: int, size: int, p2 = False) -> int: while cycles > 0: current = inp.copy() next_set = set() for point in current: c = 0 for n in point.full_neighbors(): c2 = 0 if n in current: c += 1 elif 0 <= n.x < size and 0 <= n.y < size: c2 = [p for p in n.full_neighbors() if p in current] if len(c2) == 3: next_set.add(n) if c in [2, 3]: next_set.add(point) cycles -= 1 inp = next_set.copy() if p2: inp.update({Coord(0, 0), Coord(0, 99), Coord(99, 99), Coord(99, 0)}) return len(inp)
def part1(inp: List[str]) -> str: retVal = '' retVal2 = 1 loc = Coord(inp[0].index("|"), 0) max_y = len(inp) max_x = len(inp[0]) direction = "s" directions = { "n": Coord(0, -1), "s": Coord(0, 1), "w": Coord(-1, 0), "e": Coord(1, 0) } opposites = {"n": "s", "s": "n", "w": "e", "e": "w"} loc = loc + directions[direction] uppers = list(string.ascii_uppercase) while max_x > loc.x >= 0 and max_y > loc.y >= 0: spot = inp[loc.y][loc.x] # print(loc) if spot == "+": # find which direction is next for k, v in directions.items(): if k != direction and k != opposites[direction]: n = inp[loc.y + v.y][loc.x + v.x] else: n = '' if n in ["|", "-"]: direction = k break # print(f"New direction: {direction}") elif spot == " ": # assert 0 == 1, f"We've strayed off the trail! {retVal}" return retVal, retVal2 elif spot in uppers: retVal += spot elif spot == 'E': print(spot) loc = loc + directions[direction] retVal2 += 1 return retVal, retVal2
def part2(inp: str) -> int: def neighbors(x: int, y: int) -> Set[Coord]: retVal = [] if x > 0: retVal.append(Coord(x-1, y)) if x < 127: retVal.append(Coord(x+1, y)) if y > 0: retVal.append(Coord(x, y-1)) if y < 127: retVal.append(Coord(x, y+1)) return retVal grid = part1(inp) grouped = [] groups = 0 x = y = 0 while x < 128: while y < 128: if grid[y][x] == "1": point = Coord(x, y) else: y += 1 continue if point not in grouped: groups += 1 else: y += 1 continue edges = [point] group = [point] while True: new_edges = [] for p in group: try: new_edges.extend([z for z in neighbors(p.x, p.y) if grid[z.y][z.x] == "1" and z not in group and z not in new_edges]) except IndexError: print(new_edges) return if not new_edges: break edges = new_edges.copy() group.extend(edges) grouped.extend(group) y += 1 x += 1 y = 0 assert sum(x.count('1') for x in grid) == len(grouped), "Not all items were grouped" return groups
def part2(inp: List[str]) -> int: on = {Coord(x, y): 0 for x in range(1000) for y in range(1000)} for line in inp: if line.count(" ") == 3: command, start, th, end = line.split() else: commanda, commandb, start, th, end = line.split() command = commanda + commandb start = [int(x) for x in start.split(',')] end = [int(x) for x in end.split(',')] if command == "toggle": for c in light_section(start, end): on[c] += 2 elif command == "turnoff": for c in light_section(start, end): if on[c] > 0: on[c] -= 1 else: for c in light_section(start, end): on[c] += 1 return sum(x for x in on.values())
if c in [2, 3]: next_set.add(point) cycles -= 1 inp = next_set.copy() if p2: inp.update({Coord(0, 0), Coord(0, 99), Coord(99, 99), Coord(99, 0)}) return len(inp) TEST_DATA = """.#.#.# ...##. #....# ..#... #.#..# ####..""" if __name__ == "__main__": import os, timeit FILE_DIR = os.path.dirname(os.path.abspath(__file__)) with open(os.path.join(FILE_DIR, "day18.input")) as f: DATA = f.read().strip() DATA = DATA.split("\n") LIGHTS = {Coord(x, y) for y in range(len(DATA)) for x in range(len(DATA)) if DATA[x][y] == "#"} print(f"Part one: {part1(LIGHTS, 100, len(DATA))}") # not 9996, too high; LIGHTS = {Coord(x, y) for y in range(len(DATA)) for x in range(len(DATA)) if DATA[x][y] == "#"} LIGHTS.update({Coord(0, 0), Coord(0, 99), Coord(99, 99), Coord(99, 0)}) print(f"Part two: {part1(LIGHTS, 100, len(DATA), True)}") # print(f"Time: {timeit.timeit('', setup='from __main__ import ', number = 1)}")
def light_section(start: List[int], end: List[int]) -> Set[Coord]: for x in range(start[0], end[0] + 1): for y in range(start[1], end[1] + 1): yield Coord(x, y)