Skip to content

Instantly share code, notes, and snippets.

@Radcliffe
Created January 13, 2017 00:02
Show Gist options
  • Save Radcliffe/04bb0c62069083b0e2e6956ea9c9a3a9 to your computer and use it in GitHub Desktop.
Save Radcliffe/04bb0c62069083b0e2e6956ea9c9a3a9 to your computer and use it in GitHub Desktop.
Python script to solve additive cryptarithms
#!/usr/bin/env python
# This programs solves additive cryptarithms using brute force.
# Example: solve_cryptarithm(['SEND', 'MORE', 'MONEY']) returns a list of
# all solutions to the equation SEND + MORE = MONEY, where each letter
# stands for a different digit in base 10. Leading zeros are not allowed.
from itertools import permutations
import sys
def word_to_number(word, lookup):
"""Convert a word to a number by replacing each letter with a digit, using a lookup dictionary."""
return int(''.join(str(lookup[letter]) for letter in word))
def solve_cryptarithm(words):
"""Solve an equation like SEND + MORE = MONEY given a list of three or more words.
The last word should be the sum of the other words."""
words = [word.upper() for word in words]
letters = list(set(''.join(words)))
if len(letters) > 10:
print('Too many distinct letters (%d).' % len(letters))
return
for perm in permutations(range(10), len(letters)):
lookup = dict(zip(letters, perm))
if all(lookup[w[0]] > 0 for w in words):
numbers = [word_to_number(w, lookup) for w in words]
if sum(numbers[:-1]) == numbers[-1]:
yield numbers
if __name__ == '__main__':
if len(sys.argv) < 4:
print('At least three arguments required.')
else:
for solution in solve_cryptarithm(sys.argv[1:]):
print (' + '.join(str(n) for n in solution[:-1]) + ' = ' + str(solution[-1]))
@Radcliffe
Copy link
Author

Radcliffe commented Sep 11, 2021 via email

@TonyHoldroyd
Copy link

TonyHoldroyd commented Sep 11, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment