-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Get parser working * Solve 14.a * Solve 14.b
- Loading branch information
1 parent
54e07ec
commit 2a26f9f
Showing
9 changed files
with
231 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
from dataclasses import dataclass | ||
from functools import cached_property | ||
from aoc_2023.day_14.parser import Parser | ||
|
||
|
||
@dataclass | ||
class Day14PartASolver: | ||
panel: list[list[str]] | ||
|
||
@property | ||
def solution(self) -> int: | ||
panel = self.tilt_north(self.panel) | ||
return self.count_north_load(panel) | ||
|
||
def count_north_load(self, panel: list[list[str]]) -> int: | ||
output = 0 | ||
for x in range(self.width): | ||
for y in range(self.height): | ||
if panel[y][x] == "O": | ||
output += self.height - y | ||
return output | ||
|
||
def tilt_north(self, panel: list[list[str]]) -> list[list[str]]: | ||
output = [["." for _ in range(self.width)] for _ in range(self.height)] | ||
for x in range(self.width): | ||
dest = 0 | ||
for y in range(self.height): | ||
match panel[y][x]: | ||
case ".": | ||
... | ||
case "#": | ||
output[y][x] = "#" | ||
dest = y + 1 | ||
case "O": | ||
output[dest][x] = "O" | ||
dest += 1 | ||
case _: | ||
assert False | ||
return output | ||
|
||
@cached_property | ||
def width(self) -> int: | ||
return len(self.panel[0]) | ||
|
||
@cached_property | ||
def height(self) -> int: | ||
return len(self.panel) | ||
|
||
|
||
def solve(input: str) -> int: | ||
data = Parser.parse(input) | ||
solver = Day14PartASolver(data) | ||
|
||
return solver.solution | ||
|
||
|
||
def get_solution() -> int: | ||
with open("aoc_2023/day_14/input.txt", "r") as f: | ||
input = f.read() | ||
return solve(input) | ||
|
||
|
||
if __name__ == "__main__": | ||
print(get_solution()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
from dataclasses import dataclass | ||
from functools import cached_property | ||
from aoc_2023.day_14.parser import Parser | ||
|
||
|
||
@dataclass | ||
class Day14PartBSolver: | ||
panel: list[list[str]] | ||
cycles: int = 1000000000 | ||
|
||
@property | ||
def solution(self) -> int: | ||
seen_at = dict[tuple[tuple[str, ...], ...], int]() | ||
|
||
panel = self.panel | ||
for i in range(self.cycles): | ||
panel = self.do_cycle(panel) | ||
as_tuple = tuple([tuple([x for x in line]) for line in panel]) | ||
if as_tuple in seen_at: | ||
first_sighted = seen_at[as_tuple] | ||
cycle_length = i - first_sighted | ||
cycles_left = self.cycles - i - 1 | ||
offset = cycles_left % cycle_length | ||
index = first_sighted + offset | ||
for p, j in seen_at.items(): | ||
if j == index: | ||
return self.count_north_load([[x for x in line] for line in p]) | ||
else: | ||
seen_at[as_tuple] = i | ||
return self.count_north_load(panel) | ||
|
||
def do_cycle(self, panel: list[list[str]]) -> list[list[str]]: | ||
panel = self.tilt_north(panel) | ||
panel = self.tilt_west(panel) | ||
panel = self.tilt_south(panel) | ||
panel = self.tilt_east(panel) | ||
return panel | ||
|
||
def count_north_load(self, panel: list[list[str]]) -> int: | ||
output = 0 | ||
for x in range(self.width): | ||
for y in range(self.height): | ||
if panel[y][x] == "O": | ||
output += self.height - y | ||
return output | ||
|
||
def tilt_north(self, panel: list[list[str]]) -> list[list[str]]: | ||
output = [["." for _ in range(self.width)] for _ in range(self.height)] | ||
for x in range(self.width): | ||
dest = 0 | ||
for y in range(self.height): | ||
match panel[y][x]: | ||
case ".": | ||
... | ||
case "#": | ||
output[y][x] = "#" | ||
dest = y + 1 | ||
case "O": | ||
output[dest][x] = "O" | ||
dest += 1 | ||
case _: | ||
assert False | ||
return output | ||
|
||
def tilt_south(self, panel: list[list[str]]) -> list[list[str]]: | ||
output = [["." for _ in range(self.width)] for _ in range(self.height)] | ||
for x in range(self.width): | ||
dest = self.height - 1 | ||
for y in range(self.height - 1, -1, -1): | ||
match panel[y][x]: | ||
case ".": | ||
... | ||
case "#": | ||
output[y][x] = "#" | ||
dest = y - 1 | ||
case "O": | ||
output[dest][x] = "O" | ||
dest -= 1 | ||
case _: | ||
assert False | ||
return output | ||
|
||
def tilt_west(self, panel: list[list[str]]) -> list[list[str]]: | ||
output = [["." for _ in range(self.width)] for _ in range(self.height)] | ||
for y in range(self.height): | ||
dest = 0 | ||
for x in range(self.width): | ||
match panel[y][x]: | ||
case ".": | ||
... | ||
case "#": | ||
output[y][x] = "#" | ||
dest = x + 1 | ||
case "O": | ||
output[y][dest] = "O" | ||
dest += 1 | ||
case _: | ||
assert False | ||
return output | ||
|
||
def tilt_east(self, panel: list[list[str]]) -> list[list[str]]: | ||
output = [["." for _ in range(self.width)] for _ in range(self.height)] | ||
for y in range(self.height): | ||
dest = self.width - 1 | ||
for x in range(self.width - 1, -1, -1): | ||
match panel[y][x]: | ||
case ".": | ||
... | ||
case "#": | ||
output[y][x] = "#" | ||
dest = x - 1 | ||
case "O": | ||
output[y][dest] = "O" | ||
dest -= 1 | ||
case _: | ||
assert False | ||
return output | ||
|
||
@cached_property | ||
def width(self) -> int: | ||
return len(self.panel[0]) | ||
|
||
@cached_property | ||
def height(self) -> int: | ||
return len(self.panel) | ||
|
||
|
||
def solve(input: str) -> int: | ||
data = Parser.parse(input) | ||
solver = Day14PartBSolver(data) | ||
|
||
return solver.solution | ||
|
||
|
||
def get_solution() -> int: | ||
with open("aoc_2023/day_14/input.txt", "r") as f: | ||
input = f.read() | ||
return solve(input) | ||
|
||
|
||
if __name__ == "__main__": | ||
print(get_solution()) |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
class Parser: | ||
@staticmethod | ||
def parse(input: str) -> list[list[str]]: | ||
lines = input.strip().splitlines() | ||
return [list(line) for line in lines] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from aoc_2023.day_14.a import get_solution, solve | ||
from aoc_2023.day_14.from_prompt import SAMPLE_DATA, SAMPLE_SOLUTION_A | ||
|
||
|
||
def test_solve(): | ||
assert solve(SAMPLE_DATA) == SAMPLE_SOLUTION_A | ||
|
||
|
||
def test_my_solution(): | ||
assert get_solution() == 107053 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from aoc_2023.day_14.b import get_solution, solve | ||
from aoc_2023.day_14.from_prompt import SAMPLE_DATA, SAMPLE_SOLUTION_B | ||
|
||
|
||
def test_solve(): | ||
assert solve(SAMPLE_DATA) == SAMPLE_SOLUTION_B | ||
|
||
|
||
def test_my_solution(): | ||
assert get_solution() == 88371 |