aoc-2025/10/main.py

153 lines
5.1 KiB
Python
Raw Permalink Normal View History

2025-12-10 23:19:35 -06:00
#!/usr/bin/env python3
from logging import debug, DEBUG, basicConfig
from sys import argv
2025-12-12 20:39:27 -06:00
from re import finditer
2025-12-10 23:19:35 -06:00
2025-12-12 18:28:02 -06:00
class Manual:
class Line:
light_solution: str
count_solution: str
choices: list[str]
2025-12-12 20:39:27 -06:00
def __init__(self, input_line: str):
2025-12-12 18:28:02 -06:00
self.light_solution = input_line.split()[0][1:-1]
2025-12-12 20:39:27 -06:00
self.count_solution = "".join(
input_line.split()[len(input_line.split()) - 1][1:-1]
)
2025-12-12 18:28:02 -06:00
self.choices = [x[1:-1] for x in input_line.split()[1:-1]]
self.choices.sort(key=lambda x: len(x))
2025-12-12 20:39:27 -06:00
def find_solution(self) -> list[int]:
debug("CURRENT CHOICES: %s", self.choices)
while self.count_solution != ",".join(["0" for _ in self.light_solution]):
# This needs to go back a step if we ever reach an empty best_options list...
# And iterate through the best options.
# This is probably best done with recursion.
debug("CURRENT COUNT: %s", self.count_solution)
minimum_value = str(
min([int(x) for x in self.count_solution.split(",") if int(x)])
)
minimum_indexes = [
str(i)
for i, v in enumerate(self.count_solution.split(","))
if v == minimum_value
]
debug(minimum_indexes)
best_options = [
len([v.string for v in c])
for c in [
finditer("|".join(minimum_indexes), c) for c in self.choices
]
]
debug(best_options)
solved_indexes = [
str(x)
for x in range(len(self.count_solution.split(",")))
if not int(self.count_solution.split(",")[x])
]
debug(solved_indexes)
for i, _ in enumerate(best_options):
for c in self.choices[i].split(","):
if c in solved_indexes:
best_options[i] = 0
debug(best_options)
current_choice = self.choices[best_options.index(max(best_options))]
debug(
"CURRENT CHOICE: %s",
current_choice,
)
for _ in range(int(minimum_value)):
for c in current_choice.split(","):
temp_count = self.count_solution.split(",")
temp_count[int(c)] = str(int(temp_count[int(c)]) - 1)
self.count_solution = ",".join(temp_count)
return []
2025-12-12 18:28:02 -06:00
lines: list[Line]
2025-12-12 20:39:27 -06:00
def __init__(self):
2025-12-12 18:28:02 -06:00
self.lines = []
2025-12-10 23:19:35 -06:00
def parse_input(
input_filepath: str,
2025-12-12 20:39:27 -06:00
) -> Manual:
2025-12-10 23:19:35 -06:00
with open(file=input_filepath, mode="r") as input_file:
input_data: list[str] = input_file.readlines()
debug(f"\n\nRAW INPUT: {input_data}\n\n")
# Not even trying to be legible anymore.
2025-12-12 20:39:27 -06:00
# output = [
# [segment[1:-1] for segment in line.strip().split()] for line in input_data
# ]
output = Manual()
output.lines = [Manual.Line(l) for l in input_data]
2025-12-12 00:24:27 -06:00
return output
2025-12-10 23:19:35 -06:00
2025-12-12 00:24:27 -06:00
def traverse_tree(solution: str, choices: list[str], states: set[str]) -> int:
debug("CURRENT STATES: %s", states)
2025-12-10 23:19:35 -06:00
if solution in states:
debug("FOUND IT")
return 0
2025-12-12 00:24:27 -06:00
new_states: set[str] = set()
2025-12-10 23:19:35 -06:00
for state in states:
2025-12-12 00:24:27 -06:00
for c in choices:
temp_state = state
for s in range(len(state)):
if str(s) in c.split(","):
if state[s] == ".":
2025-12-12 18:28:02 -06:00
temp_state = temp_state[:s] + "#" + temp_state[s][1:]
2025-12-12 00:24:27 -06:00
else:
2025-12-12 18:28:02 -06:00
temp_state = temp_state[:s] + "." + temp_state[s][1:]
2025-12-12 00:24:27 -06:00
new_states.add(temp_state)
2025-12-10 23:19:35 -06:00
return 1 + traverse_tree(solution, choices, new_states)
def find_shortest_solutions(
2025-12-12 00:24:27 -06:00
manual: list[list[str]],
2025-12-10 23:19:35 -06:00
) -> list[int]:
output: list[int] = []
for line in manual:
debug(
"CURRENT SOLUTION: %s\nCURRENT CHOICES: %s",
2025-12-12 00:24:27 -06:00
line[0],
[
"".join(["#" if str(x) in button else "." for x in range(len(line[0]))])
for button in line[1:-1]
],
2025-12-10 23:19:35 -06:00
)
2025-12-12 00:24:27 -06:00
output.append(traverse_tree(line[0], line[1:-1], {"".join("." * len(line[0]))}))
2025-12-10 23:19:35 -06:00
return output
def main() -> None:
2025-12-12 20:39:27 -06:00
input_filepath = "input/manual.txt"
2025-12-10 23:19:35 -06:00
input_manual = parse_input(input_filepath)
2025-12-12 20:39:27 -06:00
debug(
"MANUAL\n%s",
[
[line.light_solution, line.choices, line.count_solution]
for line in input_manual.lines
],
)
for line in input_manual.lines:
line.find_solution()
# shortest_solutions = find_shortest_solutions(input_manual)
# debug(f"SHORTEST SOLUTIONS: {shortest_solutions}")
# print(f"The sum of shortest solution is: {sum(shortest_solutions)}")
2025-12-10 23:19:35 -06:00
return
if __name__ == "__main__":
if "-d" in argv or "--debug" in argv:
basicConfig(filename="debug.log", level=DEBUG)
main()
exit(0)