import sys from pprint import pprint from copy import deepcopy def shift(map, dx, dy): for y in range(max(0, -dy), len(map) - max(0, dy)): for x in range(max(0, -dx), len(map) - max(0, dx)): (x1, y1) = (x, y) while True: (x2, y2) = (x1 + dx, y1 + dy) if 0 <= y2 < len(map) and 0 <= x2 < len(map[y2]) and map[y2][x2] == ".": (x1, y1) = (x2, y2) else: break if (x1, y1) != (x, y): map[y1][x1] = "O" map[y][x] = "." def weigh(map): return sum((len(map) - y) * row.count("O") for (y, row) in enumerate(map)) # @profile def main(): CYCLES = 1_000_000_000 with open(sys.argv[1]) as f: map = [[c for c in l] for l in f.read().strip().splitlines()] part1 = 0 pprint(map) shift(map, 0, -1) pprint(map) part1 = weigh(map) shift(map, -1, 0) pprint(map) shift(map, 0, 1) pprint(map) shift(map, 1, 0) pprint(map) for i in range(1, 100): shift(map, 0, -1) shift(map, -1, 0) shift(map, 0, 1) shift(map, 1, 0) seen = {} history = [] (i, j) = (0, 0) for i in range(100, CYCLES): shift(map, 0, -1) shift(map, -1, 0) shift(map, 0, 1) shift(map, 1, 0) s = str(map) history.append(weigh(map)) if s in seen: j = seen[s] break seen[s] = i offset = (CYCLES - j) % (i - j) - 1 part2 = history[offset] print(part1, part2) main()