# Solving number puzzles with Python

### 1. What is a number puzzle?

A rebus is an encrypted example where each number is replaced by a letter. The same number in the example must be replaced by the same letter. And vice versa – two different numbers cannot be replaced by the same letter.

And the last rule: in the example that we want to turn into a puzzle, not a single number can start with 0.

Examples of puzzles:

• EIN + EIN + EIN + EIN = VIER (1+1+1+1 = 4, German);

• BOAT + BOAT + BOAT + BOAT = REGATTA;

• BOOK + BOOK + BOOK = SCIENCE;

• SEND + MORE = MONEY (Send more money, English);

• CAT + WHO = CURRENT

And all of them will be easily solved by our program!

### 2. Structure of our program

I understand that you only care about the result, so you can immediately look at the end of the blog. However, do not be offended if you do not understand anything there and therefore cannot use it. And we will continue.

So the program should:

1. Recognize the rebus;

2. Enumerate all possible meanings of letters;

3. Check which ones are suitable;

4. Show results.

All this is quite easy, but let’s start with the most difficult one – brute force and checking, since the 1st and 4th points will occupy only one line if you know how output and input are carried out in Python. But let’s take things in order.

#### 2.1. Too much.

I decided to use it to brute force recursion. Let me first explain what recursion is. Recursive function is a function that calls itself during its execution. For example, enumerating all the moves in chess is a recursion, because we are enumerating all possible moves of ours and For each of our moves, we call the same evaluation function again for the next possible moves.

Let’s return to our search. Its structure should look something like this:

``````Функция перебор(пример):
Найти букву в примере, которую ещё не заменили на цифру;
ЕСЛИ такой буквы нету, ТО пример готов и должен проверяться, а перебор закончен ИНАЧЕ:
Для каждой цифры от 0 до 9 выполнить:
Если такая цифра уже используется в примере, она нам не подходит; взять следующию цифру;
Каждую букву в примере заменить на эту цифру;
Вызвать перебор для нового примера
``````

Now let’s rewrite this in Python:

``````def get_comb(s):
print(s + '\r', end='')
letter=""
for i in s:
if (i.isalpha()): # i.isalpha() показывает, является ли буквой переменная i
letter = i
break
if (not letter):
check(s)
return # заканчивает перебор, если пример готов
for n in range(10):
n = str(n)
if (s.find(n) > -1): continue
s2 = s.replace(letter, n)
get_comb(s2)
``````

This function replaces the letters in the puzzle with numbers, without missing any options. All we have to do is write a function `check()`which will check the example for correctness.

#### 2.2. check() function

Fortunately, we won’t have to write a long function to decipher our example and check it for correctness. After all, for Python the line “`10+29=39`“, it’s the same as a regular set of characters, he won’t understand it.

So, there is a function in Python `eval()`. This function is intended specifically for calculating examples and equalities (after all, 10+29=39 in essence is not an example, but an equality).

With this wonderful utility the function `check()` will take only 4 lines:

``````def check(s):
try:
b = eval(s.replace("=", "=="))
except: return
if (b): print(s)
``````

This function checks whether we have collected the correct equality. If an error occurs there (when the number starts with 0, `eval()` gives an error), then we consider that the equality is false (and we do the right thing, because this violates the rules of the numerical rebus).

If equality is achieved, then we found a solution to the puzzle and we can display it on the screen.
So, all that remains is to put everything together and add the rebus input.

### 3. The entire program.

Now, here’s all our code:

``````def check(s):
try:
b = eval(s.replace("=", "=="))
except: return
if (b): print(s)

def get_comb(s):
print(s + '\r', end='')
letter=""
for i in s:
if (i.isalpha()):
letter = i
break
if (not letter):
check(s)
return
for n in range(10):
n = str(n)
if (s.find(n) > -1): continue
s2 = s.replace(letter, n)
get_comb(s2)

s = (input("Введите ребус: ")).replace(" ", "") # убираем пробелы с ребуса
get_comb(s)
``````

I’ve also secured this code: you can enter the rebus by making spaces, for example by entering `кто + кот = ток` instead of `кто+кот=ток`.

So, now you can solve puzzles very quickly and even come up with your own, if, of course, you have installed Python and your computer is not too slow (for example, on my computer some puzzles take a minute or two).

Good luck!