let it go

Finished
11def solve(puzzle: str) -> dict[str, int] | None:
2 pass
2 """
3 Solve an alphametics puzzle.
4
5 Args:
6 puzzle (str): A string representing the alphametics puzzle (e.g., "SEND + MORE == MONEY")
7
8 Returns:
9 dict[str, int] | None: A dictionary mapping letters to digits that solves the puzzle,
10 or None if no solution exists.
11
12 Example:
13 >>> solve("SEND + MORE == MONEY")
14 {'S': 9, 'E': 5, 'N': 6, 'D': 7, 'M': 1, 'O': 0, 'R': 8, 'Y': 2}
15 """
16 # Edge Case: Empty or None puzzle
17 if not puzzle:
18 return None
19
20 # Parse the puzzle
21 # Edge Case: Invalid puzzle format (no '==')
22 if "==" not in puzzle:
23 return None
24
25 left_side, right_side = puzzle.split("==")
26 left_side = left_side.strip()
27 right_side = right_side.strip()
28
29 # Edge Case: Empty sides after splitting
30 if not left_side or not right_side:
31 return None
32
33 # Extract words (remove operators like +, -, etc.)
34 import re
35 words = re.findall(r'[A-Z]+', left_side + ' ' + right_side)
36
37 # Edge Case: No words found
38 if not words:
39 return None
40
41 # Get all unique letters
42 unique_letters = set(''.join(words))
43
44 # Edge Case: More than 10 unique letters (impossible to assign unique digits)
45 if len(unique_letters) > 10:
46 return None
47
48 # Get first letters of each word (can't be zero)
49 first_letters = {word[0] for word in words}
50
51 # Convert words to list for consistent ordering
52 words_list = list(words)
53
54 # Generate all possible digit assignments
55 from itertools import permutations
56
57 # Try all permutations of digits for the unique letters
58 for perm in permutations(range(10), len(unique_letters)):
59 # Create mapping from letters to digits
60 mapping = dict(zip(sorted(unique_letters), perm))
61
62 # Edge Case: Leading zero in any word
63 if any(mapping[first_letter] == 0 for first_letter in first_letters):
64 continue
65
66 # Convert words to numbers using the mapping
67 numbers = []
68 for word in words_list:
69 num = 0
70 for char in word:
71 num = num * 10 + mapping[char]
72 numbers.append(num)
73
74 # Split into left and right side numbers
75 # The last number is the result (right side)
76 result = numbers[-1]
77 operands = numbers[:-1]
78
79 # Check if the equation is satisfied
80 # For puzzles like A + B == C, we sum all but the last
81 # For puzzles like A - B == C, we need to parse operators properly
82
83 # Re-evaluate the left side with proper operators
84 # Split left_side by spaces and process
85 left_parts = left_side.split()
86 left_value = 0
87 current_op = '+' # Default starting operation
88
89 for part in left_parts:
90 if part in ['+', '-']:
91 current_op = part
92 else:
93 # It's a word
94 num = 0
95 for char in part:
96 num = num * 10 + mapping[char]
97
98 if current_op == '+':
99 left_value += num
100 elif current_op == '-':
101 left_value -= num
102
103 # Calculate right side value
104 right_value = 0
105 for char in right_side:
106 if char.isalpha():
107 right_value = right_value * 10 + mapping[char]
108
109 # Check if equation holds
110 if left_value == right_value:
111 return mapping
112
113 # Edge Case: No valid solution found
114 return None
115# Handled Edge Cases: Empty or None puzzle, Invalid puzzle format (no '=='), Empty sides after splitting, No words found, More than 10 unique letters (impossible to assign unique digits), Leading zero in any word, No valid solution found
Test NameStatus
test_puzzle_with_ten_letters_and_199_addends
Fail
test_leading_zero_solution_is_invalid
Pass
test_puzzle_with_eight_letters
Pass
test_puzzle_with_four_letters
Pass
test_puzzle_with_seven_letters
Pass
test_puzzle_with_six_letters
Pass
test_puzzle_with_ten_letters
Pass
test_puzzle_with_three_letters
Pass
test_puzzle_with_two_digits_final_carry
Pass
test_solution_must_have_unique_value_for_each_letter
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.