Дмитpий Hecтepук

Блог о программировании — C#, F#, C++, архитектура, и многое другое

Задача про 2008

2 комментария

Этот пост — репост одного моего поста который был на Hexlet до того как Hexlet решил изобрести себя снова и сдвинул мой курс в «песочницу». Он немного технический, и я не хочу его терять. Надеюсь вы поймете. К сожалению, комментарии оригинального поста потеряны, но с этим ничего не поделать.

Недавно мы с коллегой ехали на очередной эвент, и он задал мне простую, казалось бы, загадку:

Как с помощью 13 (тринадцати) нулей и простых математических операций получить число 2008?

Сразу скажу, что как количество нулей, так и число 2008 выбраны неслучайно — они не дают получить решение быстро и, более того, не дают получить слишком большое количество решений. Также, иногда эта задача (попробуйте ее пока не гуглить) дается с дополнительной подсказкой, с которой она менее интересна.

Итак, вот небольшое описание процесса рассуждений о наборе возможных решений.

Вещественность

Первый вопрос, который нужно решить — это как из нулей получать вещественные числа? Тут, естественно, имеются в виду только математические операции нежели сугубо компьютерные: например число можно инвертировать и сдвинуть, но это подразумевает что мы знаем сколько в нем бит. В общем, ограничимся математикой.

Самое очевидное решение — это 0^0 = 1 (это кстати спорно и вызвало много дебатов), но это в результате дает нам \left \lfloor{\frac{13}{2}}\right \rfloor = 6 нулей из которых, как вы понимаете, 2008 никаким образом не сделать. Должны ведь быть и другие варианты? Попробуйте угадать, какой оператор делает из нуля единицу?

Конечно же это факториал. Факториал — это обычно произведение всех чисел от 1 до n, так что например 3!=3\times2\times1, но у факториала есть одна особенность: 0!=1, а следовательно у нас теперь 13 единиц, а с ними уже можно работать. И кстати, пока не поздно, обращу внимание на то, что в условии задачи я упомянул простые математические операции. Если бы можно было использовать, например, логарифмы, то задача уже решена т.к. любое натуральное число можно выразить через логарифмы, корни, и три двойки (доказательство), а соответственно решение нашей задачи выглядело бы вот так:

\displaystyle 2008 = - \log_2\left(\log_2\left(\underbrace{\sqrt{\sqrt{...\sqrt{2}}}}_{2008}\right)\right)

Для решения выше потребовалось бы всего шесть нулей (т.к. 2 = 0! + 0!) а также 2008 квадратных корней но, как я уже сказал, хочется получить решение с помощью известных операторов, не привлекая в решение всякие сложные функции. Корни, возведение в степень, факториалы — это все ок.

Возведение в степень

Итак, нужно получить 2008. Самое очевидное — это найти близлежащее число 2^n. В данном случае, это 2^{11} и соответственно мы можем подобраться к решению вот так:

\displaystyle \begin{aligned}  2008 &= 2^{11} - 40 \\  &= 2^{2^3+3} - 5\times2^3  \end{aligned}

К сожалению, числа 2, 3 и 5 идут «по себестоимости» (т.е. чтобы сделать 5 нужно 5 нулей), и соответственно в 13 нулей мы ну никак не уложимся: для решения выше нужно аж 20 нулей!

Соответственно нашей первоочередной задачей становится поиск более «дешевых» чисел, и тут на помощь приходят…

Факториалы

Факториалы дают нам не только единицы с которыми можно работать, но также дешевые крупные числа. Например, 3!=6 а это значит что за три нуля мы можем получить не только 3 но также 6=3!, 720=(3!)!, и так далее. Если форма записи X_Y обозначает что число X требует для записи Y нулей, то мы получим следующие значения:

\displaystyle \begin{aligned}  0_1 =& 0 \\  1_1 =& 0! \\  2_2 =& 0! + 0! \\  3_3 =& 0! + 0! + 0! \\  4_4 =& 3 + 0! = 2^2 \\  5_4 =& 3! - 0! \\  6_3 =& 3! \\  7_4 =& 3! + 1 \\  8_5 =& 3! + 0! + 0! = 2^3 \\  9_5 =& 3^2  \end{aligned}

Более крупные значения (с точки зрения стоимости) лучше не трогать. И скажу сразу, что даже некоторые из значений выше мы сможем впоследствии немного улучшить.

Тем временем, мы можем начать подбираться к результату: например, разложив 2008 на множители, мы поймем что

\displaystyle \begin{aligned}  2008 &= 2^3 \times 251 \\  &= 2^3 \times (216+36-1) \\  &= 2^3 \times (6^3 + 6^2 - 1) \\  &= \underbrace{2^3 \times \left(6^2(6+1)-1)\right)}_{14}  \end{aligned}

Увы, решение выше требует на один ноль больше, чем у нас имеется.

Другой подход к решению задачи — это разложить на множители не 2008 а, скажем 2008\pm10. Вот что нам дает MATLAB:

1998=2   3   3   3  37
1999=1999
2000=2  2  2  2  5  5  5
2001=3  23  29
2002=2   7  11  13
2003=2003
2004=2    2    3  167
2005=5  401
2006=2  17  59
2007=3    3  223
2008=2    2    2  251
2009=7   7  41
2010=2   3   5  67
2011=2011
2012=2    2  503
2013=3  11  61
2014=2  19  53
2015=5  13  31
2016=2  2  2  2  2  3  3  7
2017=2017
2018=2  1009

Из интересных чисел тут, пожалуй, 2000 и 2016. Также соблазнительно число 1998 (у него есть множитель 37=3!^2+1). Возьмем сначала 2000:

\displaystyle \begin{aligned}  2000 =& \underbrace{2^4\times5^3}_{12} \\  =& \underbrace{2\times\left(2^{3}+2\right)^3}_{11}  \end{aligned}

Это решение нам явно не подходит т.к. 2008 = 2000+8_5 т.е. для решения нужно 16 единиц. Попробуем 2016:

\displaystyle \begin{aligned}  2016 =& \underbrace{2^3\times6^2\times7}_{14} \\  =& \underbrace{6^4+(3!)!}_{10}  \end{aligned}

Но даже так, у нас остается три нуля, а 2008=2016-8_5, то есть для этого решения нам всяко не хватает двух нулей. Что же, подход с обычными (намек!) факториалами почти себя исчерпал, давайте еще попробуем что-нибудь сделать с числом 1998:

\displaystyle \begin{aligned}  1998 &= \underbrace{3!^2\times\left(3!^2+1\right)}_{11}  \end{aligned}

Это достаточно бессмысленное занятие т.к. двумя нулями лишние 10 не набрать, но, по крайней мере, мы выловили тот факт, что возможно стоит попробовать 3!^4:

\displaystyle \begin{aligned}  2008 &= 3!^4 + 712 \\  &= \underbrace{3!^4 + (3!)! - 2^3}_{15}  \end{aligned}

Увы и ах. Как я уже говорил в самом начале, число 2008 выбрано неслучайно — это число вставляет максимальное число палок в колеса. Нужен какой-то трюк чтобы снизить «стоимость» простых чисел вроде 8. К счастью, такой трюк имеется, и это…

Двойной факториал

Двойной факториал n!! — это тоже произведение всех чисел от 1 до n, но с шагом 2, т.к. например 5!!=5\times3\times1=15. Само по себе это кардинально меняет картину, и я хочу обратить ваше внимание на два равенства:

  • 8_4 = 4!!, то есть восьмерка стала «дешевле» на один ноль.

  • 48_3=(3!)!!

Итак, делим 2008 на 48 и получаем 41.8(3), а поскольку 42=6\times7, мы наконец-то можем попробовать получить ответ:

\displaystyle \begin{aligned}  2008 &= 48\times42-8 \\  &= \underbrace{(3!)!!\times\left(3!\times(3!+1)\right)-4!!}_{14}  \end{aligned}

Но что-то тут не так: 42 нам далось адским трудом, мы заплатили за него аж 7 нулей. На один ноль поменьше и все получится. На самом же деле, 42=48-6=(3!)!!-3! и вот, ура, у нас готово первое решение:

\displaystyle 2008 = \underbrace{(3!)!!\times\left((3!)!!-3!\right)-4!!}_{13}

Субфакториал

Разных факториалов бывает много и субфакториалы — это такой особый тип факториала, который определяет количество беспорядков порядка n. Высчитывается он так

\displaystyle !n=n!\sum_{k=0}^n \frac{\left(-1\right)^k}{k!}

Прелесть этого факториала в том, что он в очередной раз дает нам другие равенства, например 265_3 = !(3!). А это в свою очередь заставляет нас в очередной раз посмотреть на разложение 2008 на множители:

\displaystyle \begin{aligned}  2008 &= 4!! \times 251 \\  &= 4!! \times (!(3!) - 14) \\  &= \underbrace{4!! \times \left(!(3!)-5!!+1\right)}_{13}  \end{aligned}

Оптимизация задачи

Кому-то может показаться, что 13 нулей — это предел мечтания, но нет — вот например пара решений, где используются только 12 нулей:

\displaystyle \begin{aligned}  2008 &= \underbrace{(!5)^2 + \sqrt{\left((3!)!+1\right)} + 1}_{12} \\  &= \underbrace{\left(!(4!!)-1\right)\times2+5!}_{12}  \end{aligned}

Предлагаю игру в стиле code golf — оставляйте в комментариях решения, которые используют 11 нулей и меньше, посмотрим чье кунг‑фу лучше. No cheating! ■

Advertisements

Written by Dmitri

15 февраля 2016 в 0:39

Опубликовано в Mathematics

Tagged with

комментария 2

Subscribe to comments with RSS.

  1. Всё никак в толк не возьму, почему вдруг в число простых математических операций входит факториал, но не входит логарифм? Можно линк на определение «простых математических операций»?

    Петя

    15 февраля 2016 at 11:42

    • Ну под «простой операцией» подразумевался изначально один отдельно взятый оператор (например !!). Но интерпретировать можно по-всякому, конечно же.

      Dmitri

      15 февраля 2016 at 12:06


Оставить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: