harrison

Finished
1from itertools import permutations
2
13def solve(puzzle: str) -> dict[str, int] | None:
2 pass
4 """
5 Solve an alphametics puzzle.
6
7 Args:
8 puzzle: A string representing the alphametics puzzle (e.g., "SEND + MORE == MONEY")
9
10 Returns:
11 A dictionary mapping letters to digits that solves the puzzle, or None if no solution exists.
12
13 The function handles the following edge cases:
14 - Invalid puzzle format (no '==')
15 - Words with leading zeros
16 - No valid solutions
17 """
18 # Edge Case: Invalid puzzle format (no '==')
19 if "==" not in puzzle:
20 return None
21
22 # Split the puzzle into left and right sides
23 left_side, right_side = puzzle.split("==")
24 left_side = left_side.strip()
25 right_side = right_side.strip()
26
27 # Parse the left side to extract words and operators
28 import re
29 tokens = re.findall(r'([A-Z]+|[+\-*/])', left_side)
30
31 # Extract words and operators
32 words = []
33 operators = []
34 for i, token in enumerate(tokens):
35 if token in '+-*/':
36 operators.append(token)
37 else:
38 words.append(token)
39
40 # Add the right side word
41 words.append(right_side)
42
43 # Get all unique letters in the puzzle
44 letters = set("".join(words))
45
46 # Edge Case: Too many unique letters (more than 10)
47 if len(letters) > 10:
48 return None
49
50 # Get the first letter of each word (these cannot be zero)
51 first_letters = {word[0] for word in words}
52
53 # Try all possible digit assignments
54 for perm in permutations(range(10), len(letters)):
55 mapping = dict(zip(letters, perm))
56
57 # Edge Case: Leading zero in any word
58 if any(mapping[word[0]] == 0 for word in words):
59 continue
60
61 # Convert words to numbers using the current mapping
62 numbers = []
63 for word in words:
64 number = 0
65 for char in word:
66 number = number * 10 + mapping[char]
67 numbers.append(number)
68
69 # Evaluate the left side expression
70 left_result = numbers[0]
71 for i, op in enumerate(operators):
72 if op == '+':
73 left_result += numbers[i + 1]
74 elif op == '-':
75 left_result -= numbers[i + 1]
76 elif op == '*':
77 left_result *= numbers[i + 1]
78 elif op == '/':
79 # Handle division - ensure no division by zero and exact division
80 if numbers[i + 1] == 0 or left_result % numbers[i + 1] != 0:
81 left_result = None
82 break
83 left_result //= numbers[i + 1]
84
85 # Check if the left side result equals the right side
86 if left_result is not None and left_result == numbers[-1]:
87 return mapping
88
89 # Edge Case: No valid solution found
90 return None
91
92# Handled Edge Cases: Invalid puzzle format (no '=='), Too many unique letters (more than 10), Leading zero in any word, 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.