def parse_line(line): """ Parse a line into spring states and group sizes. """ try: parts = line.strip().split() states = parts[0] group_sizes = [int(x) for x in parts[1].split(',')] return states, group_sizes except Exception as e: print(f"Error parsing line '{line}': {e}") raise 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): if states[i] == '#': if size_index >= len(group_sizes): return False # More broken springs than groups count = 0 while i < len(states) and states[i] == '#': 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 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] if states[index] != '?': memo[key] = count_configurations(states, group_sizes, index + 1, memo) return memo[key] count = 0 for state in ['.', '#']: states[index] = state count += count_configurations(states, group_sizes, index + 1, memo) states[index] = '?' memo[key] = count return count 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 with open(file_path, 'r') as file: 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 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.") 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 if __name__ == "__main__": main()