Finished
11def solve(puzzle: str) -> dict[str, int] | None:
2 pass
2 """
3 Solve an alphametics puzzle.
4
5 Args:
6 puzzle: A string representing the alphametics puzzle (e.g., "SEND + MORE == MONEY")
7
8 Returns:
9 A dictionary mapping letters to digits that solves the puzzle, or None if no solution exists.
10
11 Example:
12 >>> solve("SEND + MORE == MONEY")
13 {'S': 9, 'E': 5, 'N': 6, 'D': 7, 'M': 1, 'O': 0, 'R': 8, 'Y': 2}
14 """
15 # Edge Case: Empty or None puzzle
16 if not puzzle:
17 return None
18
19 # Parse the puzzle
20 parts = puzzle.replace("==", "=").replace(" ", "")
21
22 # Edge Case: Invalid puzzle format (no equals sign)
23 if "=" not in parts:
24 return None
25
26 left_part, right_side = parts.split("=", 1)
27
28 # Determine the operator
29 if "+" in left_part:
30 operator = "+"
31 left_sides = left_part.split("+")
32 elif "-" in left_part:
33 operator = "-"
34 left_sides = left_part.split("-")
35 elif "*" in left_part:
36 operator = "*"
37 left_sides = left_part.split("*")
38 else:
39 # Single term on left side
40 operator = None
41 left_sides = [left_part]
42
43 # Edge Case: No terms on the left side
44 if not left_sides:
45 return None
46
47 # Extract all unique letters
48 letters = set()
49 for part in left_sides + [right_side]:
50 letters.update(part)
51
52 # Edge Case: No letters in puzzle
53 if not letters:
54 return None
55
56 # Extract first letters (can't be zero)
57 first_letters = {word[0] for word in left_sides + [right_side]}
58
59 # Convert to sorted list for consistent ordering
60 letters = list(letters)
61
62 # Edge Case: More than 10 unique letters (impossible to assign unique digits)
63 if len(letters) > 10:
64 return None
65
66 # Try all possible digit assignments
67 from itertools import permutations
68
69 # Generate all possible digit permutations for the letters
70 for perm in permutations(range(10), len(letters)):
71 mapping = dict(zip(letters, perm))
72
73 # Edge Case: Leading zero in any number
74 if any(mapping[first_letter] == 0 for first_letter in first_letters):
75 continue
76
77 # Calculate values of left side terms
78 left_values = []
79 for word in left_sides:
80 value = 0
81 for char in word:
82 value = value * 10 + mapping[char]
83 left_values.append(value)
84
85 # Calculate value of right side
86 right_value = 0
87 for char in right_side:
88 right_value = right_value * 10 + mapping[char]
89
90 # Check if the equation is satisfied based on operator
91 if operator == "+":
92 if sum(left_values) == right_value:
93 return mapping
94 elif operator == "-":
95 # For subtraction, we assume the format is "A - B == C" meaning A - B = C
96 if len(left_values) == 2 and left_values[0] - left_values[1] == right_value:
97 return mapping
98 elif operator == "*":
99 # For multiplication, we assume the format is "A * B == C" meaning A * B = C
100 if len(left_values) == 2 and left_values[0] * left_values[1] == right_value:
101 return mapping
102 else:
103 # Single term on left side, should equal right side
104 if len(left_values) == 1 and left_values[0] == right_value:
105 return mapping
106
107 # Edge Case: No valid solution found
108 return None
109
110# Handled Edge Cases: Empty or None puzzle, Invalid puzzle format, No terms on left side, No letters in puzzle, More than 10 unique letters, Leading zero in any number, No valid solution found
Test NameStatus
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_ten_letters_and_199_addends
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.