From 46edd68a1c5528b81946785541f783653fcd038a Mon Sep 17 00:00:00 2001 From: Christoph Stahl Date: Thu, 14 Dec 2023 20:06:48 +0100 Subject: [PATCH] Day 14 --- aoc/day14.py | 175 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 156 insertions(+), 19 deletions(-) diff --git a/aoc/day14.py b/aoc/day14.py index 6bc6b69..72a36e7 100644 --- a/aoc/day14.py +++ b/aoc/day14.py @@ -1,6 +1,5 @@ from __future__ import annotations from typing import TypeAlias -from collections import defaultdict from .aoc import Aoc2, AocSameParser from .day11 import Matrix @@ -14,34 +13,172 @@ class Day14(AocSameParser[P1], Aoc2[P1, P2]): return Matrix(inpt) def part1(self, inpt: P1) -> int: - pos_matrix = {} + o_pos: frozenset[tuple[int, int]] = frozenset( + (o.x, o.y) for o in inpt.finditer("O") + ) + for p in o_pos: + inpt[p] = "." + + north_matrix = {} for y in range(0, inpt.height): # enumerate(inpt.iter_rows()): for x in range(0, inpt.width): # enumerate(line): - pos_matrix[x, y] = (x, y) + north_matrix[x, y] = (x, y) if y > 0: if inpt[x, y - 1] == ".": - pos_matrix[x, y] = pos_matrix[x, y - 1] - if inpt[x, y - 1] == "O": - p = pos_matrix[x, y - 1] - pos_matrix[x, y] = (p[0], p[1] + 1) + north_matrix[x, y] = north_matrix[x, y - 1] + new_o_pos = [] + for ox, oy in o_pos: + new_x, new_y = north_matrix[ox, oy] + while (new_x, new_y) in new_o_pos: + new_y += 1 + new_o_pos.append((new_x, new_y)) - accum = 0 - for o in inpt.finditer("O"): - # print( - # f"{o} -> {pos_matrix[(o.x,o.y)]} ({inpt.height - pos_matrix[(o.x,o.y)][1]})" - # ) - accum += inpt.height - pos_matrix[(o.x, o.y)][1] - - print(accum) - - return accum + return sum(inpt.height - oy for _, oy in new_o_pos) def part2(self, inpt: P2) -> int: - return 0 + o_pos: frozenset[tuple[int, int]] = frozenset( + (o.x, o.y) for o in inpt.finditer("O") + ) + for p in o_pos: + inpt[p] = "." + + north_matrix = {} + for y in range(0, inpt.height): # enumerate(inpt.iter_rows()): + for x in range(0, inpt.width): # enumerate(line): + north_matrix[x, y] = (x, y) + if y > 0: + if inpt[x, y - 1] == ".": + north_matrix[x, y] = north_matrix[x, y - 1] + + west_matrix = {} + for y in range(0, inpt.height): # enumerate(inpt.iter_rows()): + for x in range(0, inpt.width): # enumerate(line): + west_matrix[x, y] = (x, y) + if x > 0: + if inpt[x - 1, y] == ".": + west_matrix[x, y] = west_matrix[x - 1, y] + + south_matrix = {} + for y in reversed(range(0, inpt.height)): # enumerate(inpt.iter_rows()): + for x in range(0, inpt.width): # enumerate(line): + south_matrix[x, y] = (x, y) + if y < inpt.height - 1: + if inpt[x, y + 1] == ".": + south_matrix[x, y] = south_matrix[x, y + 1] + + east_matrix = {} + for y in range(0, inpt.height): # enumerate(inpt.iter_rows()): + for x in reversed(range(0, inpt.width)): # enumerate(line): + east_matrix[x, y] = (x, y) + if x < inpt.width - 1: + if inpt[x + 1, y] == ".": + east_matrix[x, y] = east_matrix[x + 1, y] + + cache = {} + stepsize = -1 + loopstart = -1 + + for i in range(1_000_000_000): + # for i in range(2): + north_pos = set() + for ox, oy in o_pos: + new_x, new_y = north_matrix[ox, oy] + while (new_x, new_y) in north_pos: + new_y += 1 + north_pos.add((new_x, new_y)) + + # west + west_pos = set() + for ox, oy in north_pos: + new_x, new_y = west_matrix[ox, oy] + while (new_x, new_y) in west_pos: + new_x += 1 + west_pos.add((new_x, new_y)) + + # south + south_pos = set() + for ox, oy in west_pos: + new_x, new_y = south_matrix[ox, oy] + while (new_x, new_y) in south_pos: + new_y -= 1 + south_pos.add((new_x, new_y)) + + # east + east_pos = set() + for ox, oy in south_pos: + new_x, new_y = east_matrix[ox, oy] + while (new_x, new_y) in east_pos: + new_x -= 1 + east_pos.add((new_x, new_y)) + + o_pos = frozenset(east_pos) + + # north_matrix = {} + # for y in range(0, inpt.height): # enumerate(inpt.iter_rows()): + # for x in range(0, inpt.width): # enumerate(line): + # north_matrix[x, y] = (x, y) + # if y > 0: + # if (x, y - 1) in o_pos: + # p = north_matrix[x, y - 1] + # north_matrix[x, y] = (p[0], p[1] + 1) + # elif inpt[x, y - 1] == ".": + # north_matrix[x, y] = north_matrix[x, y - 1] + # o_pos = frozenset(north_matrix[pos] for pos in o_pos) + # + # west_matrix = {} + # for y in range(0, inpt.height): # enumerate(inpt.iter_rows()): + # for x in range(0, inpt.width): # enumerate(line): + # west_matrix[x, y] = (x, y) + # if x > 0: + # if (x - 1, y) in o_pos: + # p = west_matrix[x - 1, y] + # west_matrix[x, y] = (p[0] + 1, p[1]) + # elif inpt[x - 1, y] == ".": + # west_matrix[x, y] = west_matrix[x - 1, y] + # o_pos = frozenset(west_matrix[pos] for pos in o_pos) + # + # south_matrix = {} + # for y in reversed(range(0, inpt.height)): # enumerate(inpt.iter_rows()): + # for x in range(0, inpt.width): # enumerate(line): + # south_matrix[x, y] = (x, y) + # if y < inpt.height - 1: + # if (x, y + 1) in o_pos: + # p = south_matrix[x, y + 1] + # south_matrix[x, y] = (p[0], p[1] - 1) + # elif inpt[x, y + 1] == ".": + # south_matrix[x, y] = south_matrix[x, y + 1] + # o_pos = frozenset(south_matrix[pos] for pos in o_pos) + # + # east_matrix = {} + # for y in range(0, inpt.height): # enumerate(inpt.iter_rows()): + # for x in reversed(range(0, inpt.width)): # enumerate(line): + # east_matrix[x, y] = (x, y) + # if x < inpt.width - 1: + # if (x + 1, y) in o_pos: + # p = east_matrix[x + 1, y] + # east_matrix[x, y] = (p[0] - 1, p[1]) + # elif inpt[x + 1, y] == ".": + # east_matrix[x, y] = east_matrix[x + 1, y] + # o_pos = frozenset(east_matrix[pos] for pos in o_pos) + if o_pos in cache: + if stepsize < 0: + loopstart = cache[o_pos] + stepsize = i - cache[o_pos] + if cache[o_pos] == (1000000000 - loopstart) % stepsize + loopstart - 1: + break + else: + cache[o_pos] = i + + accum = 0 + for _, oy in o_pos: + accum += inpt.height - oy + for p in o_pos: + inpt[p] = "O" + return accum def main() -> None: - aoc = Day14(2023, 14) + aoc = Day14(2023, 14, example_code_nr2=0) aoc.run()