perfect

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(" ", "").split("=")
21
22 # Edge Case: Invalid puzzle format (no equals sign or too many parts)
23 if len(parts) != 2:
24 return None
25
26 right_side = parts[1]
27 left_expression = parts[0]
28
29 # Extract operators and operands from the left side
30 import re
31 # Find all operators (+, *, -)
32 operators = re.findall(r'[+*-]', left_expression)
33 # Split by operators to get operands
34 operands = re.split(r'[+*-]', left_expression)
35
36 # Edge Case: No terms on the left side
37 if not operands or not operands[0]:
38 return None
39
40 left_parts = operands
41
42 # Extract all unique letters
43 letters = set()
44 for part in left_parts + [right_side]:
45 letters.update(part)
46
47 # Edge Case: No letters in puzzle
48 if not letters:
49 return None
50
51 # Extract first letters (can't be zero)
52 first_letters = {word[0] for word in left_parts + [right_side]}
53
54 # Convert letters to a list for indexing
55 letters_list = list(letters)
56
57 # Edge Case: More than 10 unique letters (impossible to assign unique digits)
58 if len(letters_list) > 10:
59 return None
60
61 # Try all permutations of digits for the letters
62 from itertools import permutations
63
64 # Edge Case: Handle permutation generation for different numbers of letters
65 for perm in permutations(range(10), len(letters_list)):
66 mapping = dict(zip(letters_list, perm))
67
68 # Check if any first letter is assigned zero
69 if any(mapping[letter] == 0 for letter in first_letters):
70 continue
71
72 # Calculate the value of the left side based on operators
73 if not operators:
74 # Single term on left side
75 left_value = 0
76 for letter in left_parts[0]:
77 left_value = left_value * 10 + mapping[letter]
78 else:
79 # Multiple terms with operators
80 # Convert each word to number
81 numbers = []
82 for word in left_parts:
83 number = 0
84 for letter in word:
85 number = number * 10 + mapping[letter]
86 numbers.append(number)
87
88 # Apply operators in order (left to right)
89 left_value = numbers[0]
90 for i, op in enumerate(operators):
91 if op == '+':
92 left_value += numbers[i + 1]
93 elif op == '*':
94 left_value *= numbers[i + 1]
95 elif op == '-':
96 left_value -= numbers[i + 1]
97
98 # Calculate the right side value
99 right_value = 0
100 for letter in right_side:
101 right_value = right_value * 10 + mapping[letter]
102
103 # Check if the equation is satisfied
104 if left_value == 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, First letters assigned zero, 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.