\besttop

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 propagation 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 - Invalid puzzle format (no '==')
16 - Words with invalid characters
17 - Leading zeros in multi-digit words
18 - No solution exists
19 - Empty or malformed puzzle string
20 """
21 # Edge Case: Empty or malformed puzzle string
22 if not puzzle or "==" not in puzzle:
23 return None
24
25 # Parse the puzzle
26 left_side, right_side = puzzle.replace(" ", "").split("==")
27 addends = left_side.split("+")
28 result = right_side
29
30 # Edge Case: Invalid puzzle format (no addends or result)
31 if not addends or not result:
32 return None
33
34 # Collect all unique letters
35 letters = set()
36 for word in addends + [result]:
37 # Edge Case: Words with invalid characters
38 if not word.isalpha():
39 return None
40 letters.update(word)
41
42 # Edge Case: More than 10 unique letters (impossible to assign unique digits)
43 if len(letters) > 10:
44 return None
45
46 # Identify first letters (can't be zero)
47 first_letters = {word[0] for word in addends + [result]}
48
49 # Convert words to lists of characters for easier processing
50 addend_chars = [list(word) for word in addends]
51 result_chars = list(result)
52
53 # Prepare variables for backtracking
54 letters_list = list(letters)
55 digits = [None] * len(letters_list) # digits[i] corresponds to letters_list[i]
56 used_digits = [False] * 10
57
58 def is_valid_assignment():
59 """Check if current digit assignment satisfies the equation."""
60 # Build number mappings
61 letter_to_digit = {letters_list[i]: digits[i] for i in range(len(letters_list)) if digits[i] is not None}
62
63 # Check for leading zeros
64 for word in addends + [result]:
65 # Edge Case: Leading zeros in multi-digit words
66 if len(word) > 1 and letter_to_digit[word[0]] == 0:
67 return False
68
69 # Convert addends and result to numbers
70 try:
71 addend_nums = []
72 for word_chars in addend_chars:
73 num = 0
74 for char in word_chars:
75 num = num * 10 + letter_to_digit[char]
76 addend_nums.append(num)
77
78 result_num = 0
79 for char in result_chars:
80 result_num = result_num * 10 + letter_to_digit[char]
81
82 return sum(addend_nums) == result_num
83 except KeyError:
84 # Not all letters have been assigned yet
85 return False
86
87 def backtrack(index):
88 """Backtracking function to assign digits to letters."""
89 # Base case: all letters have been assigned
90 if index == len(letters_list):
91 if is_valid_assignment():
92 return True
93 return False
94
95 letter = letters_list[index]
96
97 # Try each digit from 0 to 9
98 for digit in range(10):
99 # Skip if digit is already used
100 if used_digits[digit]:
101 continue
102
103 # Skip if this is a first letter and digit is 0
104 # Edge Case: Leading digit of a multi-digit number must not be zero
105 if letter in first_letters and digit == 0:
106 continue
107
108 # Assign digit
109 digits[index] = digit
110 used_digits[digit] = True
111
112 # Recurse
113 if backtrack(index + 1):
114 return True
115
116 # Backtrack
117 digits[index] = None
118 used_digits[digit] = False
119
120 return False
121
122 # Start backtracking
123 if backtrack(0):
124 # Build and return the solution dictionary
125 solution = {letters_list[i]: digits[i] for i in range(len(letters_list))}
126 return solution
127 else:
128 # Edge Case: No solution exists
129 return None
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.