Konoha

Finished
1from itertools import permutations
2import re
3
14def solve(puzzle: str) -> dict[str, int] | None:
2 pass
5 """
6 Solve an alphametics puzzle.
7
8 Args:
9 puzzle: A string representing the alphametics puzzle (e.g., "SEND + MORE == MONEY")
10
11 Returns:
12 A dictionary mapping letters to digits that solves the puzzle, or None if no solution exists.
13
14 Example:
15 >>> solve("SEND + MORE == MONEY")
16 {'S': 9, 'E': 5, 'N': 6, 'D': 7, 'M': 1, 'O': 0, 'R': 8, 'Y': 2}
17 """
18 # Edge Case: Empty or None puzzle
19 if not puzzle:
20 return None
21
22 # Parse the puzzle - handle both == and =, and extract operators
23 puzzle = puzzle.replace("==", "=")
24 parts = puzzle.split("=")
25
26 # Edge Case: Invalid puzzle format
27 if len(parts) != 2:
28 return None
29
30 right_side = parts[1].strip()
31 left_expression = parts[0].strip()
32
33 # Extract terms and operators from left side
34 # Handle both + and * operators
35 terms = re.findall(r'[A-Z]+', left_expression)
36 operators = re.findall(r'[+*]', left_expression)
37
38 # Edge Case: No terms on the left side
39 if not terms:
40 return None
41
42 # Get all unique letters
43 all_words = terms + [right_side]
44 letters = set("".join(all_words))
45
46 # Edge Case: More than 10 unique letters (impossible to solve)
47 if len(letters) > 10:
48 return None
49
50 # Get first letters (can't be zero)
51 first_letters = {word[0] for word in all_words if len(word) > 1}
52
53 # Get all letters as a list for consistent ordering
54 all_letters = list(letters)
55
56 # Try all digit permutations
57 for perm in permutations(range(10), len(letters)):
58 mapping = dict(zip(all_letters, perm))
59
60 # Edge Case: Leading zero
61 if any(mapping[letter] == 0 for letter in first_letters):
62 continue
63
64 # Convert words to numbers using the mapping
65 term_values = []
66 for term in terms:
67 number = 0
68 for letter in term:
69 number = number * 10 + mapping[letter]
70 term_values.append(number)
71
72 # Calculate right side value
73 right_value = 0
74 for letter in right_side:
75 right_value = right_value * 10 + mapping[letter]
76
77 # Calculate left side result based on operators
78 if not operators:
79 # Single term on left side
80 left_result = term_values[0]
81 else:
82 # Apply operations in order (left to right)
83 left_result = term_values[0]
84 for i, op in enumerate(operators):
85 if op == '+':
86 left_result += term_values[i + 1]
87 elif op == '*':
88 left_result *= term_values[i + 1]
89
90 # Check if equation is satisfied
91 if left_result == right_value:
92 return mapping
93
94 # Edge Case: No solution found
95 return None
96
97# Handled Edge Cases: Empty or None puzzle, Invalid puzzle format, No terms on the left side, More than 10 unique letters, Leading zero, No 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.