ИТ
November 22, 2021

Перебор с бэктрекингом

Задача - имеется три слова, первые два - слогаемые, третье - сумма. Подобрать кодировку для букв, чтобы равенство было верно.

Логика такая же, как в задаче с 8 ферзями - имеется поле с размерами: по вертикали имеется диапазон с 10 числами от нуля до девяти, по горизонтали диапазон в размере уникальных символов.

Перебор заключается в том, что начиная с первого символа "фишку" необходимо попытаться поставить как можно ближе к нулю на незанятый ряд (при этом учитывая, что если символ является первым в одном из слов - он не может быть равен нулю).

Когда последний символ уже некуда ставить, возвращаем его в -1 и возвращаемся к предудущему символу, двигаем его вперед и начинаем снова перебирать последний символ.

Когда предпоследний символ дошёл до крайнего значения, возвращаем его в null и сдвигаем предыдущий по счету символ и начинаем снова перебирать предпоследний символ и так далее.

Когда все символы одновременно дошли до превого значения - перебор закончен. Если в какой-то момент перебора было удовлетворено условие равенства - сохраняем набор значений ключей в массив.

Бэктрекинг заключается в том, что когда перебраны все элементы следующего уровня, мы возвращаемся на предыдущий и берем следующий элемент.

Логика функции для перебора значений выглядит так:

решалка {
      индекс буквы в массиве = 0;
      пока индекс буквы >= 0 {
         если значение символа < 9 {
            значение символа ++;
            если значение не занято другими символами {
               если индекс буквы < количества букв {
                  перейти к следующей букве;
               } еще если текущее состояние значений является решением {
                  .. сделать что требовалось сделать ..;
               }
            }
         } в ином случае {
            вернуть значение символа в начальное положение;
            вернуться к предыдущй букве;
         }
      }
   }

Для проверки, не занято ли значение для символа каким-либо из других символов существует отдельная фукнция.

цифра не занята {
      если цифра является первой и текущее значение равно нулю
         занято
      для каждой предыдущей буквы в массиве {
         если значение предыдущей буквы равно значению текущей буквы
            вернуть занято
      }
      вернуть свободно
   }