Skip to content

Commit

Permalink
py day 13 part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
shouples committed Dec 22, 2023
1 parent 12e8c56 commit 620ffcc
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ For the non-notebook sections, tests (`pytest` and `cargo nextest`) are be inclu
| 10 | ✅⛔ | ✅⛔ | ✅⛔ | |
| 11 | ✅✅ | ✅✅ | 🕒🕒 | |
| 12 | ✅⛔ | ✅⛔ | 🕒🕒 | Getting pretty tired of the "do part 1 but with way more data" trend here. |
| 13 | ✅⛔ | 🕒🕒 | 🕒🕒 | Multiple examples were working in part 2, but something isn't quite working correctly on the actual inputs. |
| 13 | ✅⛔ | ✅⛔ | 🕒🕒 | Multiple examples were working in part 2, but something isn't quite working correctly on the actual inputs. |
| 14 | ✅⛔ | ✅⛔ | 🕒🕒 | |
| 15 | ✅✅ | ✅✅ | 🕒🕒 | This was a nice little break compared to the past week's puzzle offerings. |
| 16 | ✅✅ | 🕒🕒 | 🕒🕒 | |
Expand Down
89 changes: 89 additions & 0 deletions py/solutions/day13_1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from typing import Optional

import pandas as pd
from IPython.display import Markdown
from solutions.utils import timer


def find_mirror_position(df: pd.DataFrame, v: bool = False, show=False) -> Optional[int]:
max_score = 0
for i in range(1, len(df) + 1):
if i == len(df):
# can't split on the last row
continue

top_rows = df.iloc[:i]
bottom_rows = df.iloc[i:]

if len(top_rows) > len(bottom_rows):
# shorten top rows
top_rows = top_rows.tail(len(bottom_rows))
elif len(top_rows) < len(bottom_rows):
# shorten bottom rows
bottom_rows = bottom_rows.head(len(top_rows))

# flip the bottom rows' index positions so they (potentially) match the top
bottom_rows = bottom_rows.iloc[::-1]

assert len(bottom_rows) == len(top_rows)

# string comparisons on just the values is better than trying to compare the whole dataframe
# portions, which will include the index values and columns by default
t = top_rows.to_string(index=False, header=False)
b = bottom_rows.to_string(index=False, header=False)
if t == b:
df_copy = df.copy()
if v:
# debug_df = debug_df.transpose()
df_copy = df_copy.transpose()

# last row's index + 1 in `top_rows` is the position of the mirror line
last_index = top_rows.index[-1] + 1
# 1x for mirroring against a vertical line, 100x for a horizontal line
score = last_index * 100 if not v else last_index

max_score += score
return max_score


def find_mirror_lines(data: str, show: bool = False):
rows = data.split("\n")
df = pd.DataFrame([list(line) for line in rows]).astype(int)

score = 0

horizontal_line_score = find_mirror_position(df, show=show)
if horizontal_line_score is not None:
score += horizontal_line_score

vertical_line_score = find_mirror_position(df.transpose(), v=True, show=show)
if vertical_line_score is not None:
score += vertical_line_score

return score


@timer
def solve(inputs: list[str]) -> int:
"""High-level solution logic to call additional functions as needed."""
total_score = 0
for block in inputs:
total_score += find_mirror_lines(block)
return total_score


@timer
def load_input() -> list[str]:
"""Read from an input file and handle any preprocessing."""
return open("../inputs/13.txt").read().strip().replace("#", "1").replace(".", "0").split("\n\n")


@timer
def run() -> None:
inputs: list[str] = load_input()
solution = solve(inputs)
print(f"{solution=}")


if __name__ == "__main__":
run()
27 changes: 24 additions & 3 deletions py/tests/day13.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,32 @@
import pytest
from solutions import day13_1


@pytest.mark.skip(reason="TODO")
def test_part1():
pass
input_str = (
"""
#.##..##.
..#.##.#.
##......#
##......#
..#.##.#.
..##..##.
#.#.##.#.
#...##..#
#....#..#
..##..###
#####.##.
#####.##.
..##..###
#....#..#""".strip()
.replace("#", "1")
.replace(".", "0")
.split("\n\n")
)
assert day13_1.solve(input_str) == 405


@pytest.mark.skip(reason="TODO")
@pytest.mark.skip(reason="admitted defeat 😢")
def test_part2():
pass

0 comments on commit 620ffcc

Please sign in to comment.