from lib import * EXAMPLE = """ O....#.... O.OO#....# .....##... OO.#O....O .O.....O#. O.#..O.#.# ..O..#O..O .......O.. #....###.. #OO..#.... """ def get_nth_elem(xs, n): """ Find the nth element of a repeating sequence. """ found = set() x = None for (i, x) in enumerate(xs): if x in found: break found.add(x) if i is None: raise Exception("No repeating sequence.") first_repeat = i initial_sequence_length = xs.index(x) repeating_sequence_length = first_repeat - xs.index(x) adjusted_n = n - initial_sequence_length position_in_repeating_sequence = adjusted_n % repeating_sequence_length element = xs[initial_sequence_length + position_in_repeating_sequence] return element def solve(i: Input, second=False): res = 0 g = i.grid2() if second: dirs = [Grid2D.N, Grid2D.W, Grid2D.S, Grid2D.E] cycles = 1000000000 else: dirs = [Grid2D.N] cycles = 1 fs = {} v = [] for i in range(cycles): h = hash(tuple(g.find('O'))) fs[h] = tuple(g.find('O')) v.append(h) if v.count(h) > 1: break for d in dirs: moved = True while moved: moved = False for r in g.find('O'): rn = add2(r, d) if rn in g and g[rn] == '.': g[r] = '.' g[rn] = 'O' moved = True if second: h = get_nth_elem(v, 1000000000) os = fs[h] for r, c in os: s = g.n_rows - r res += s else: for r, c in g.find('O'): s = g.n_rows - r res += s return res def main(): DAY_INPUT = "i14.txt" print("Example 1:", solve(Input(EXAMPLE))) print("Solution 1:", solve(Input(DAY_INPUT))) # 5:55 print("Example 2:", solve(Input(EXAMPLE), True)) print("Solution 2:", solve(Input(DAY_INPUT), True)) # 48:00 if __name__ == "__main__": main()