advent_of_code_2023/Day12/python/solution1.py

116 lines
3.1 KiB
Python
Raw Normal View History

2023-12-12 17:12:55 +00:00
def parse_line(line):
"""
Parse a line into spring states and group sizes.
"""
try:
parts = line.strip().split()
states = parts[0]
2023-12-12 18:35:31 +00:00
group_sizes = [int(x) for x in parts[1].split(",")]
2023-12-12 17:12:55 +00:00
return states, group_sizes
except Exception as e:
print(f"Error parsing line '{line}': {e}")
raise
2023-12-12 18:35:31 +00:00
2023-12-12 17:12:55 +00:00
def is_valid_configuration(states, group_sizes):
"""
Check if a given configuration of springs is valid based on group sizes.
"""
try:
i, size_index = 0, 0
while i < len(states):
2023-12-12 18:35:31 +00:00
if states[i] == "#":
2023-12-12 17:12:55 +00:00
if size_index >= len(group_sizes):
return False # More broken springs than groups
count = 0
2023-12-12 18:35:31 +00:00
while i < len(states) and states[i] == "#":
2023-12-12 17:12:55 +00:00
count += 1
i += 1
if count != group_sizes[size_index]:
return False # Group size mismatch
size_index += 1
else:
i += 1
return size_index == len(group_sizes) # All groups must be accounted for
except Exception as e:
print(f"Error in is_valid_configuration: {e}")
raise
2023-12-12 18:35:31 +00:00
2023-12-12 17:12:55 +00:00
def count_configurations(states, group_sizes, index=0, memo=None):
"""
Count the number of valid configurations using backtracking and memoization.
"""
if memo is None:
memo = {}
key = (tuple(states), index)
if key in memo:
return memo[key]
if index == len(states):
memo[key] = 1 if is_valid_configuration(states, group_sizes) else 0
return memo[key]
2023-12-12 18:35:31 +00:00
if states[index] != "?":
2023-12-12 17:12:55 +00:00
memo[key] = count_configurations(states, group_sizes, index + 1, memo)
return memo[key]
count = 0
2023-12-12 18:35:31 +00:00
for state in [".", "#"]:
2023-12-12 17:12:55 +00:00
states[index] = state
count += count_configurations(states, group_sizes, index + 1, memo)
2023-12-12 18:35:31 +00:00
states[index] = "?"
2023-12-12 17:12:55 +00:00
memo[key] = count
return count
2023-12-12 18:35:31 +00:00
2023-12-12 17:12:55 +00:00
def solve_puzzle(file_path):
"""
Solve the puzzle for each line in the file and return the total count of configurations.
"""
try:
total_count = 0
2023-12-12 18:35:31 +00:00
with open(file_path, "r") as file:
2023-12-12 17:12:55 +00:00
for line in file:
states, group_sizes = parse_line(line)
count = count_configurations(list(states), group_sizes)
total_count += count
print(f"Line: {line.strip()}, Possible Configurations: {count}")
return total_count
except Exception as e:
print(f"Error in solve_puzzle: {e}")
raise
2023-12-12 18:35:31 +00:00
2023-12-12 17:12:55 +00:00
def test():
"""
Test the solution with a test file.
"""
print("Running tests...")
test_result = solve_puzzle("../test.txt")
print(f"Test Result: {test_result}")
assert test_result == 21, f"Test failed, expected 21, got {test_result}"
print("Test passed successfully.")
2023-12-12 18:35:31 +00:00
2023-12-12 17:12:55 +00:00
def main():
"""
Main function to run the test and then solve the puzzle.
"""
try:
test()
result = solve_puzzle("../input.txt")
print(f"Final Result: {result}")
except Exception as e:
print(f"Error in main: {e}")
raise
2023-12-12 18:35:31 +00:00
2023-12-12 17:12:55 +00:00
if __name__ == "__main__":
main()