uv

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 The function uses backtracking with constraint checking to find a valid digit assignment
12 where each letter represents a unique digit, no leading digit is zero, and the equation holds.
13
14 Handled Edge Cases:
15 - Empty or whitespace-only puzzle strings
16 - Puzzles with no equality operator
17 - Puzzles with invalid syntax
18 - Puzzles with no valid solutions
19 - Puzzles with leading zeros in multi-digit numbers
20 """
21 # Edge Case: Empty or whitespace-only puzzle
22 if not puzzle or not puzzle.strip():
23 return None
24
25 # Parse the puzzle
26 # Edge Case: Puzzle without equality operator
27 if "==" not in puzzle:
28 return None
29
30 try:
31 left_side, right_side = puzzle.replace(" ", "").split("==")
32 addends = left_side.split("+")
33
34 # Edge Case: Invalid puzzle syntax (no addends)
35 if not addends or not all(addends) or not right_side:
36 return None
37 except ValueError:
38 # Edge Case: Malformed puzzle string
39 return None
40
41 # Extract all unique letters
42 letters = set()
43 for part in addends + [right_side]:
44 letters.update(part)
45
46 # Edge Case: No letters in puzzle
47 if not letters:
48 return None
49
50 # Identify first letters (can't be zero)
51 first_letters = {word[0] for word in addends + [right_side]}
52
53 # Convert to sorted list for consistent ordering
54 letters = list(letters)
55
56 def is_valid_solution(mapping):
57 """Check if the current mapping is a valid solution."""
58 # Check for leading zeros
59 # Edge Case: Leading zero in any multi-digit number
60 for word in addends + [right_side]:
61 if len(word) > 1 and mapping[word[0]] == 0:
62 return False
63
64 # Calculate values
65 try:
66 addend_values = []
67 for word in addends:
68 value = 0
69 for char in word:
70 value = value * 10 + mapping[char]
71 addend_values.append(value)
72
73 result_value = 0
74 for char in right_side:
75 result_value = result_value * 10 + mapping[char]
76
77 return sum(addend_values) == result_value
78 except KeyError:
79 # Edge Case: Not all letters have been assigned yet
80 return False
81
82 def backtrack(index, mapping, used_digits):
83 """Recursive backtracking function to find a solution."""
84 # Base case: all letters have been assigned
85 if index == len(letters):
86 if is_valid_solution(mapping):
87 return mapping.copy()
88 return None
89
90 letter = letters[index]
91
92 # Try each digit from 0-9
93 for digit in range(10):
94 # Skip if digit is already used
95 if digit in used_digits:
96 continue
97
98 # Skip if this is a first letter and digit is 0
99 # Edge Case: Prevent leading zeros
100 if letter in first_letters and digit == 0:
101 continue
102
103 # Try this digit assignment
104 mapping[letter] = digit
105 used_digits.add(digit)
106
107 # Recurse
108 result = backtrack(index + 1, mapping, used_digits)
109 if result is not None:
110 return result
111
112 # Backtrack
113 del mapping[letter]
114 used_digits.remove(digit)
115
116 return None
117
118 # Start backtracking
119 solution = backtrack(0, {}, set())
120 return solution
121
122# Handled Edge Cases:
123# - Empty or whitespace-only puzzle strings
124# - Puzzles with no equality operator
125# - Puzzles with invalid syntax
126# - Puzzles with no valid solutions
127# - Puzzles with leading zeros in multi-digit numbers
128# - Malformed puzzle strings
129# - Puzzles with no letters
130# - Not all letters have been assigned during validation
131# - Preventing leading zeros in multi-digit numbers
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.