So, every letter is correspondent with a number, so
(a=1, b=2, c=3,...z=26),
and I don’t know how to replace the string with integers so that an input string of
('COUPLE + COUPLE = QUARTET')
would output
('653924 + 653924 = 1307848')
Module imports are prohibited
I have tried tweaking past solutions from other posts, but they all return None, or something different.
This is my code currently:
def alphametics(puzzle):
return [ord(char) - 96 for char in puzzle.lower()]
and
def alphametics(puzzle):
is the input. The input will always be uppercase, and will always be valid, so no need to check for that.
and when my input is this:
'SEND + MORE = MONEY'
my output is this:
[19, 5, 14, 4, -64, -53, -64, 13, 15, 18, 5, -64, -35, -64, 13, 15, 14, 5, 25]
but it should be this:
'9567 + 1085 = 10652'
Some puzzles may have multiple valid solutions; my function only needs to return one:
'BIG + CAT = LION
403 + 679 = 1082
326 + 954 = 1280
304 + 758 = 1062
...etc.'
The objective is to replace the letters of the alphabet with decimal digits to make a valid arithmetic sum.
Requirements:
A naive, brute-force algorithm may time out before the first test completes.
Each unique letter may only be assigned to one unique digit
As a corollary to the above, there will be a maximum of 10 unique letters in any given test
No leading zeroes
The equations will only deal with addition with multiple summands on the left side and one term on the right side
The number of summands will range between 2 and 7, inclusive
The length of each summand will range from 2 to 8 characters, inclusive
4
Try using the approach mentioned at itertools.permutations
since “Module imports are prohibited”:
import re
from typing import TypeVar
from collections.abc import Iterable
T = TypeVar('T')
# From https://docs.python.org/3/library/itertools.html#itertools.permutations.
def permutations(iterable: Iterable[T], r: int | None = None):
# permutations('ABCD', 2) → AB AC AD BA BC BD CA CB CD DA DB DC
# permutations(range(3)) → 012 021 102 120 201 210
pool = tuple(iterable)
n = len(pool)
r = n if r is None else r
if r > n:
return
indices = list(range(n))
cycles = list(range(n, n-r, -1))
yield tuple(pool[i] for i in indices[:r])
while n:
for i in reversed(range(r)):
cycles[i] -= 1
if cycles[i] == 0:
indices[i:] = indices[i+1:] + indices[i:i+1]
cycles[i] = n - i
else:
j = cycles[i]
indices[i], indices[-j] = indices[-j], indices[i]
yield tuple(pool[i] for i in indices[:r])
break
else:
return
def extract_s1_s2_s3(puzzle: str) -> tuple[str, str, str] | None:
"""Extracts S1, S2, and S3 from the alphametic puzzle string.
Args:
puzzle: A string representing the alphametic equation
(e.g., 'SEND + MORE = MONEY').
Returns:
A tuple (S1, S2, S3) if the puzzle format is valid, or None if invalid.
"""
match = re.match(r'(w+)s*+s*(w+)s*=s*(w+)', puzzle)
if not match:
return None
return match.groups()
def solve_alphametic(S1: str, S2: str, S3: str) -> tuple[int, int, int] | str:
"""Solves the alphametic problem S1 + S2 = S3.
Args:
S1: The first string operand in the equation.
S2: The second string operand in the equation.
S3: The result string in the equation.
Returns:
A tuple (N1, N2, N3) representing the solution if it exists,
or 'UNSOLVABLE' otherwise.
"""
letters = set(S1 + S2 + S3)
digits = '0123456789'
for perm in permutations(digits, len(letters)):
mapping = {letter: digit for letter, digit in zip(letters, perm)}
if mapping[S1[0]] == '0' or mapping[S2[0]] == '0' or mapping[S3[0]] == '0':
continue # Leading zeros are not allowed
N1 = int(''.join(mapping[char] for char in S1))
N2 = int(''.join(mapping[char] for char in S2))
N3 = int(''.join(mapping[char] for char in S3))
if N1 + N2 == N3:
return N1, N2, N3
return 'UNSOLVABLE'
def main() -> None:
"""Main function to execute the alphametic solver."""
puzzle = input('Enter the alphametic puzzle (e.g., "SEND + MORE = MONEY"): ')
parts = extract_s1_s2_s3(puzzle)
if parts is None:
print('Invalid puzzle format')
return
S1, S2, S3 = parts
solution = solve_alphametic(S1, S2, S3)
if solution == 'UNSOLVABLE':
print(solution)
else:
a, b, c = solution
print(f'{a} + {b} = {c}')
if __name__ == '__main__':
main()
Example Usage 1:
Enter the alphametic puzzle (e.g., "SEND + MORE = MONEY"): SEND + MORE = MONEY
9567 + 1085 = 10652
Example Usage 2:
Enter the alphametic puzzle (e.g., "SEND + MORE = MONEY"): COUPLE + COUPLE = QUARTET
653924 + 653924 = 1307848
4
This can be done using the .join function that will loop through each character in your string, then reference the alphabet to number dictionary map and convert the input string accordingly.
You will need to likely change create_alphabet_to_number_map()
or alphabet_to_number
for a custom alphametic map, since the example I provided is just a=1, b=2, and so forth…
# Create a dictionary of your conversions
def create_alphabet_to_number_map():
# Create a map from alphabet letters A-J to corresponding numbers 0-9
alphabet_to_number = {chr(65 + i): str(i) for i in range(26)}
return alphabet_to_number
# Apply conversion function to every character
def convert_string_using_map(input_string):
# Create the alphabet-to-number map
alphabet_to_number = create_alphabet_to_number_map()
# Convert the input string using the map
converted_string = ''.join([alphabet_to_number.get(char, char) for char in input_string])
return converted_string
# Example usage
input_string = "Couple + Couple = Quartet"
converted_string = convert_string_using_map(input_string.upper())
print(f"Original String: {input_string}")
print(f"Converted String: {converted_string}")
1