-
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.
- Loading branch information
Showing
3 changed files
with
262 additions
and
0 deletions.
There are no files selected for viewing
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,59 @@ | ||
import typer | ||
from itertools import combinations | ||
import re | ||
|
||
|
||
def spring_conditions_satisfies_group( | ||
spring_conditions: list[str], groups: list[int] | ||
) -> bool: | ||
for s, i in zip(spring_conditions, groups): | ||
if len(s) != i: | ||
return False | ||
return True | ||
|
||
|
||
def build_regex_from_groups(groups: list[int]) -> str: | ||
regex = r"^[?|\.]*" | ||
for i, group in enumerate(groups): | ||
if i > 0: | ||
regex += r"[?|\.]+" | ||
regex += rf"[#|?]{{{group}}}" | ||
regex += r"[?|\.]*$" | ||
return regex | ||
|
||
|
||
def build_regex_from_group(group: int) -> str: | ||
regex = r"[^|[?|\.]+]" | ||
regex += rf"[#|?]{{{group}}}" | ||
regex += r"[?|\.]*$" | ||
return regex | ||
|
||
def decipher_spring_conditions( | ||
spring_conditions: str, groups: list[int] | ||
) -> str: | ||
# spring_conditions = [s for s in spring_conditions.split(".") if s != ""] | ||
# damaged_groups = [int(i) for i in damaged_groups.split(",")] | ||
|
||
s = "." + spring_conditions + "." | ||
|
||
for g in groups: | ||
|
||
|
||
|
||
return len(list(matches)) | ||
|
||
|
||
def main(input_file: typer.FileText): | ||
input = input_file.read().strip().split("\n") | ||
for i in input: | ||
i = i.split(" ") | ||
spring_conditions = i[0] | ||
groups = i[1] | ||
num_solutions = decipher_spring_conditions( | ||
spring_conditions, [int(g) for g in groups.split(",")] | ||
) | ||
print(f"Number of solutions: {num_solutions}") | ||
|
||
|
||
if __name__ == "__main__": | ||
typer.run(main) |
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,88 @@ | ||
import typer | ||
from itertools import combinations, groupby | ||
|
||
|
||
def print_matrix(matrix: list[str], title: str | None = None, details: bool = | ||
False) -> None: | ||
if title: | ||
print(title) | ||
if details: | ||
print(f"Rows: {len(matrix)}, Columns: {len(matrix[0])}") | ||
if details: | ||
for i, row in enumerate(matrix): | ||
print(f"{row} {i}") | ||
else: | ||
for row in matrix: | ||
print(row) | ||
|
||
print() | ||
|
||
|
||
def transpose(matrix: list[str]) -> list[str]: | ||
t = list(zip(*matrix)) | ||
return ["".join(row) for row in t] | ||
|
||
|
||
def find_reflection(pattern: list[str]) -> int | None: | ||
for r in range(1, len(pattern)): | ||
side_a = pattern[:r] | ||
side_b = pattern[r:] | ||
side_a = side_a[-len(side_b) :] | ||
side_b = side_b[: len(side_a)] | ||
side_b.reverse() | ||
# print_matrix(side_a, "Side A:", True) | ||
# print_matrix(side_b, "Side B:", True) | ||
if side_a == side_b: | ||
return r | ||
return None | ||
|
||
|
||
def find_reflection_with_smudge(pattern: list[str]) -> int | None: | ||
for r in range(1, len(pattern)): | ||
side_a = pattern[:r] | ||
side_b = pattern[r:] | ||
side_a = side_a[-len(side_b) :] | ||
side_b = side_b[: len(side_a)] | ||
side_b.reverse() | ||
inequalities = 0 | ||
for row_a, row_b in zip(side_a, side_b): | ||
inequalities += sum(a != b for a, b in zip(row_a, row_b)) | ||
if inequalities > 1: | ||
break | ||
if inequalities == 1: | ||
#print_matrix(side_a, "Side A:", True) | ||
#print_matrix(side_a, "Side B:", True) | ||
return r | ||
return None | ||
|
||
def calc_magic_sum_for_patterns(patterns: list[list[str]], fn) -> int: | ||
sum = 0 | ||
for pattern in patterns: | ||
# print_matrix(pattern, "Finding reflection for pattern:") | ||
reflection = fn(pattern) | ||
if reflection: | ||
print(f"Reflection found on row {reflection}") | ||
sum += reflection * 100 | ||
continue | ||
reflection = fn(transpose(pattern)) | ||
if reflection: | ||
print(f"Reflection found on column {reflection}") | ||
sum += reflection | ||
continue | ||
raise "Reflection not found" | ||
return sum | ||
|
||
|
||
def main(input_file: typer.FileText): | ||
input = input_file.read().strip().split("\n") | ||
patterns = [list(g) for k, g in groupby(input, key=bool) if k] | ||
|
||
sum = calc_magic_sum_for_patterns(patterns, find_reflection) | ||
print(f"Part 1: Sum: {sum}") | ||
|
||
sum = calc_magic_sum_for_patterns(patterns, find_reflection_with_smudge) | ||
print(f"Part 2: Sum: {sum}") | ||
|
||
|
||
if __name__ == "__main__": | ||
typer.run(main) |
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,115 @@ | ||
import typer | ||
from itertools import combinations, groupby | ||
|
||
|
||
def transpose(matrix: list[str]) -> list[str]: | ||
t = list(zip(*matrix)) | ||
return ["".join(row) for row in t] | ||
|
||
|
||
def rotate_right(matrix: list[str]) -> list[str]: | ||
return transpose(matrix[::-1]) | ||
|
||
|
||
def rotate_left(matrix: list[str]) -> list[str]: | ||
return transpose(matrix)[::-1] | ||
|
||
|
||
def tilt_west(matrix: list[str]) -> list[str]: | ||
new_matrix = [] | ||
for row in matrix: | ||
rock = 0 | ||
new_row = "" | ||
|
||
row_rocks = row.split("#") | ||
for i, part in enumerate(row.split("#")): | ||
if i > 0: | ||
new_row += "#" | ||
new_row += "".join([c for c in part if c == "O"]) | ||
new_row += "".join([c for c in part if c == "."]) | ||
|
||
new_matrix.append(new_row) | ||
return new_matrix | ||
|
||
|
||
def tilt_north(matrix: list[str]) -> list[str]: | ||
matrix = rotate_left(matrix) | ||
matrix = tilt_west(matrix) | ||
matrix = rotate_right(matrix) | ||
return matrix | ||
|
||
|
||
def tilt_east(matrix: list[str]) -> list[str]: | ||
matrix = rotate_left(rotate_left(matrix)) | ||
matrix = tilt_west(matrix) | ||
matrix = rotate_right(rotate_right(matrix)) | ||
return matrix | ||
|
||
|
||
def tilt_south(matrix: list[str]) -> list[str]: | ||
matrix = rotate_right(matrix) | ||
matrix = tilt_west(matrix) | ||
matrix = rotate_left(matrix) | ||
return matrix | ||
|
||
|
||
def get_load(matrix: list[str]) -> int: | ||
return sum( | ||
[row.count("O") * (i + 1) for i, row in enumerate(reversed(matrix))] | ||
) | ||
|
||
|
||
def print_matrix(matrix: list[str]) -> None: | ||
for row in matrix: | ||
print(row) | ||
|
||
|
||
def cycle_matrix(matrix: list[str]) -> int: | ||
matrix = tilt_north(matrix) | ||
matrix = tilt_west(matrix) | ||
matrix = tilt_south(matrix) | ||
matrix = tilt_east(matrix) | ||
return matrix | ||
|
||
|
||
def find_offset_period(matrix: list[str]) -> int: | ||
seen = [] | ||
seen.append(hash(tuple(matrix))) | ||
while True: | ||
matrix = cycle_matrix(matrix) | ||
h = hash(tuple(matrix)) | ||
if h in seen: | ||
return (seen.index(h), len(seen) - seen.index(h)) | ||
seen.append(h) | ||
|
||
|
||
def main(input_file: typer.FileText): | ||
dish = input_file.read().strip().split("\n") | ||
|
||
print_matrix(dish) | ||
print() | ||
d = tilt_north(dish) | ||
print_matrix(d) | ||
|
||
print(f"Part 1: load: {get_load(d)}") | ||
|
||
offset, period = find_offset_period(dish) | ||
print(f"offset: {offset}, period: {period}") | ||
|
||
d = dish | ||
print(f"Cycling for {offset} times") | ||
for _ in range(offset): | ||
d = cycle_matrix(d) | ||
|
||
print(f"Cycling for {(1000000000 - offset) % period} times") | ||
for _ in range((1000000000 - offset) % period): | ||
d = cycle_matrix(d) | ||
|
||
print("Final state:") | ||
print_matrix(d) | ||
|
||
print(f"Part 2: load: {get_load(d)}") | ||
|
||
|
||
if __name__ == "__main__": | ||
typer.run(main) |