relax

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 # Parse the puzzle
16 # Edge Case: Invalid puzzle format
17 if "==" not in puzzle:
18 return None
19
20 left_side, right_side = puzzle.split("==")
21 left_side = left_side.strip()
22 right_side = right_side.strip()
23
24 # Extract words (remove operators and spaces)
25 words = []
26 for part in left_side.split("+"):
27 words.append(part.strip())
28 words.append(right_side)
29
30 # Edge Case: Empty words
31 if any(not word for word in words):
32 return None
33
34 # Get all unique letters
35 letters = set()
36 for word in words:
37 letters.update(word)
38
39 # Edge Case: More than 10 unique letters (impossible to assign unique digits)
40 if len(letters) > 10:
41 return None
42
43 # Get first letters (can't be zero)
44 first_letters = {word[0] for word in words}
45
46 # Convert letters to a list for consistent ordering
47 letters_list = list(letters)
48
49 def evaluate(words, mapping):
50 """Evaluate the numeric values of words given a letter-to-digit mapping."""
51 numbers = []
52 for word in words:
53 num = 0
54 for char in word:
55 num = num * 10 + mapping[char]
56 numbers.append(num)
57 return numbers
58
59 def is_valid_solution(mapping):
60 """Check if the current mapping satisfies the puzzle equation."""
61 numbers = evaluate(words, mapping)
62 # Sum of all but the last number should equal the last number
63 return sum(numbers[:-1]) == numbers[-1]
64
65 def backtrack(index, used_digits, mapping):
66 """Backtracking function to find a valid letter-to-digit mapping."""
67 # Base case: all letters have been assigned
68 if index == len(letters_list):
69 if is_valid_solution(mapping):
70 return mapping.copy()
71 return None
72
73 letter = letters_list[index]
74
75 # Try each digit from 0 to 9
76 for digit in range(10):
77 # Skip if digit is already used
78 if digit in used_digits:
79 continue
80
81 # Skip if this is a first letter and digit is 0
82 if letter in first_letters and digit == 0:
83 continue
84
85 # Assign digit to letter
86 mapping[letter] = digit
87 used_digits.add(digit)
88
89 # Recurse to next letter
90 result = backtrack(index + 1, used_digits, mapping)
91 if result is not None:
92 return result
93
94 # Backtrack
95 del mapping[letter]
96 used_digits.remove(digit)
97
98 return None
99
100 # Start backtracking with empty mapping
101 solution = backtrack(0, set(), {})
102 return solution
103
104# Handled Edge Cases: Invalid puzzle format, empty words, more than 10 unique letters
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.