Задача для дата-сайентистов
medium

Задача для дата-сайентистов

Это будет сложно.

Сложная задачка, готовьтесь.

Подставьте вместо букв цифры, чтобы получилось верное равенство:

ОДИН + ОДИН = МНОГО

Одна цифра — одна буква. Это значит, что нельзя, например, число 5 заменить одновременно на буквы А и Б и наоборот.

Сначала у нас будет интеллигентное решение логикой, а потом — грубый грязный программерский перебор.

Сила этой задачи в том, что нам нужно держать в голове одновременно много факторов, которые могут влиять друг на друга. Чтобы не запутаться, мы пронумеруем наши шаги, и каждый новый шаг будет основываться на предыдущем.

1. Сначала обращаем внимание на количество цифр: складываем два четырёхзначных числа и получаем одно пятизначное, которое начинается с буквы М. Это значит, что М = 1, ведь даже если мы возьмём самое большое четырёхзначное число 9999 и сложим с самим собой, то получим 19998, то есть всё равно будет единица в самом начале.

👉 М = 1

2. Отсюда же следует вывод, что О больше или равно 5, потому что у нас увеличилось число разрядов в ответе. Если бы О было 4 или меньше, то мы бы сложили эти два четырёхзначных числа и в результате тоже бы получили четырёхзначное.

3. Смотрим теперь на самые последние символы в каждом числе: Н + Н = О. Когда складываются два одинаковых числа, это то же самое, что умножить их на два. А при умножении на два мы всегда получаем чётное число. Получается, что О — чётное, но из пункта 2 мы знаем, что О больше или равно 5. Значит, О = 6 или О = 8.

4. Теперь смотрим на третий разряд нашего сложения: Д + Д = О. Из третьего пункта мы знаем, что О — чётное число, поэтому И + И не дадут в сумме больше 10 и единица не перенесётся в О. Это значит, что И меньше 5.

5. А теперь самое сложное: у нас в разрядах есть Н + Н = О (пункт 3) и Д + Д = О. Так как цифры Д и Н — разные, но в сумме дают одинаковый результат О, то это значит, что в каком-то одном случае у нас получается число больше 10. Единица переносится на другой разряд, а оставшаяся цифра будет одинаковой.

6. Развиваем мысль дальше. Из пункта 3 мы знаем, что О = 6 или О = 8. Получается, что если О = 6, то Н = 3 (3 + 3 = 6) или Н = 8 (8 + 8 = 16). А если О = 8, то Н = 4 (4 + 4 = 8) или Н = 9 (9 + 9 = 18). Теперь подставим по очереди каждое такое значение и посмотрим, что из этого получится:

О = 6 Н = 3: значит, Д должно быть равно 8, чтобы получить 6 в первом разряде. Проверяем:

Д + Д = О → 8 + 8 = 16 (да, а единицу переносим)

Н + Н = О → 3 + 3 = 6 (да)

О + О (из начала ОДИН + ОДИН) + 1 (перенесли единицу из Д + Д) = 13 (в МНОГО М = 1, а Н = 3), значит, О + О + 1 = 13 → О = 6 (всё совпало).

О = 6 Н = 8: значит, Д должно быть равно 3.

Проверяем:

Д + Д = О → 3 + 3 = 6 (да)

Н + Н = О → 8 + 8 = 16 (да, а единицу переносим)

О + О (из начала ОДИН + ОДИН) = 13 (в МНОГО М = 1, а Н = 8), значит, О + О = 18 → О = 9 (противоречие, у нас О = 6).

О = 8 Н = 4: значит, Д должно быть равно 9, чтобы получить 8 в первом разряде. Проверяем:

Д + Д = О → 9 + 9 = 18 (да, а единицу переносим)

Н + Н = О → 4 + 4 = 8 (да)

О + О (из начала ОДИН + ОДИН) + 1 (перенесли единицу из Д + Д) = 14 (в МНОГО М = 1, а Н = 4), значит, О + О + 1 = 14 → О = 6,5 (противоречие, да и цифры не могут быть дробными).

О = 8 Н = 9: значит, Д должно быть равно 4.

Проверяем:

Д + Д = О → 4 + 4 = 8 (да)

Н + Н = О → 9 + 9 = 18 (да, а единицу переносим)

О + О (из начала ОДИН + ОДИН) = 14 (в МНОГО М = 1, а Н = 9), значит, О + О = 19 → О = 9,5 (противоречие, да и цифры не могут быть дробными).

👉 Получается, что О = 6, Н = 3, а Д = 8.

7. Смотрим на второй разряд: И + И = Г. Так как И меньше 5, а цифры 1 и 3 уже заняты, то И = 2 или И = 4. И не может быть нолём, потому что у нас не переносится единица из Н + Н, а 0 + 0 = 0.

Если И = 2, то Г = 4, а если И = 4, то Г = 8. Но 8 у нас уже обозначается буквой Д, поэтому И не может быть равно 4. Остаётся вариант: И = 2, Г = 4.

👉 И = 2, Г = 4.

Подставляем цифры вместо букв и получаем правильный ответ: 6823 + 6823 = 13646.

Если вы дочитали до конца и не запутались в буквах и цифрах — приходите в Практикум. Если запутались — всё равно приходите, поможем разобраться.

Тут врывается горе-программист. Он смотрит на условия задачи, и ему кажется, что её можно решить простым перебором. Так как он завтракает не за рабочим компьютером, он открывает консоль браузера и пишет код на JavaScript:

1. Сразу завернем всё в функцию, чтобы когда нашлось нужное значение, просто выйти из неё. И сразу её запускаем, чтобы код исполнялся:

function calculate_this_shit(){ }

calculate_this_shit();

2. Какие нам нужны переменные? Назовем их буквами:

function calculate_this_shit(){

var o, d, i, n, m, g;

}

calculate_this_shit();

3. Можно было бы как-то по-умному все эти буквы перебирать в массиве, но мне лень. Я хочу просто перебрать их шестью вложенными друг в друга циклами, используя грубую копипасту. Смысл в том, что мы перебираем цифры от 0 до 9 и проверяем наши значения на соответствие условиям задачи. Чтобы проверить их на соответствие, мы умножаем, например, букву О на 1000, букву Д на 100, букву И на 10 и букву Н на единицу. И так же с правой частью.

function calculate_this_shit() {
  var o, d, i, n, m, g;
  for (o = 0; o < 10; o++) {
    for (d = 0; d < 10; d++) {
      for (i = 0; i < 10; i++) {
        for (n = 0; n < 10; n++) {
          for (m = 0; m < 10; m++) {
            for (g = 0; g < 10; g++) {
              var left = o * 1000 + d * 100 + i * 10 + n * 1;
              var right = m * 10000 + n * 1000 + o * 100 + g * 10 + o;
              if (2 * left == right && right > 999) {
                return ('Выражение: ' + left + ' + ' + left + ' = ' + right);
              }
            }
          }
        }
      }
    }
  }
}
calculate_this_shit();

Если запустить этот код, мы получим результат:

Выражение: 6803 + 6803 = 13606

Тут нарушено условие, что каждой букве должна быть присвоена своя цифра. А у нас два раза встречается ноль: на букве И и на букве Г. Значит, нужен такой алгоритм:

  1. Когда уравнение совпало, нужно затолкать все буквы в массив.
  2. Отсортировать этот массив по возрастанию или убыванию.
  3. Проверить, нет ли в массиве повторов.
  4. И только если нет — разрешить выдать результат. А если повторы есть — искать дальше.

Неохота сейчас писать самому все эти проверки, поэтому берем код со Стек-оверфлоу:

if (2 * left == right && right > 999) {
  // По умолчанию ставим флаг, что дубликатов нет
  var foundDuplicate = false;
  // Заталкиваем наши буквы в массив
  var all = [o, d, i, n, m, g];
  // Сортируем массив
  var sorted_all = all.slice().sort();
  // Перебираем массив в поисках дубликатов
  for (let i = 0; i < sorted_all.length - 1; i++) {
    if (sorted_all[i + 1] == sorted_all[i]) {
      // Если дубликат найден, ставим флаг
      var foundDuplicate = true;
    }
  }
  //И только если флаг не стоит...
  if (foundDuplicate == false) {
    return ('Выражение: ' + left + ' + ' + left + ' = ' + right);
  }
}

Теперь будет работать. Итоговый код в расхлопе:

function calculate_this_shit() {
  var o, d, i, n, m, g;
  for (o = 0; o < 10; o++) {
    for (d = 0; d < 10; d++) {
      for (i = 0; i < 10; i++) {
        for (n = 0; n < 10; n++) {
          for (m = 0; m < 10; m++) {
            for (g = 0; g < 10; g++) {
              var left = o * 1000 + d * 100 + i * 10 + n * 1;
              var right = m * 10000 + n * 1000 + o * 100 + g * 10 + o;
              if (2 * left == right && right > 999) {
                var foundDuplicate = false;
                var all = [o, d, i, n, m, g];
                var sorted_all = all.slice().sort();
                for (let i = 0; i < sorted_all.length - 1; i++) {
                  if (sorted_all[i + 1] == sorted_all[i]) {
                    var foundDuplicate = true;
                  }
                }
                if (foundDuplicate == false) {
                  return ('Выражение: ' + left + ' + ' + left + ' = ' + right);
                }

              }
            }
          }

        }
      }
    }
  }
}
calculate_this_shit();

Любите данные? Посмотрите вот это
Возможно, у вас получится построить карьеру в мире дата-сайенса. Это новое направление, в котором очень нужны люди. Изучите эту сферу и начните карьеру в ИТ: старт — бесплатно, а после обучения — помощь с трудоустройством.
Начать бесплатно
Любите данные? Посмотрите вот это Любите данные? Посмотрите вот это Любите данные? Посмотрите вот это Любите данные? Посмотрите вот это
Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Начать карьеру в ИТ
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Еще по теме
medium