Pull to refresh
205.7
МойОфис
Платформа для работы с документами и коммуникаций

Переворачиваем список целых чисел

Reading time4 min
Views10K
Original author: Arthur O’Dwyer

Недавно Александр Муньис опубликовал новую математическую игру, которую назвал «Переверни список целых чисел». Заключается она в следующем.

  • Составьте список разных положительных чисел (например, 10 5 3). Ваша цель — перевернуть список, используя «ходы» двух видов:

  • Разделите одно из чисел на две части, которые в сумме дают целое; например, (10 5 4) может стать (7 3 5 4) или (10 2 3 4).

  • Объедините два соседних числа в их сумму; например, (7 3 5 4) может стать (7 8 4) или (7 3 9).

Нельзя образовывать число, которое больше максимального числа в исходном списке. Например, если мы пытаемся изменить (10 5 4), то (7 5 3 4) может стать (7 8 4), но не может стать (12 3 4), так как 12 больше, чем 10 — максимальное число исходного списка. Также все элементы списка должны оставаться различными; например, (7 5 3 4) не может стать ни (7 5 7), ни (7 2 3 3 4).

Александр спрашивает: какие эффективные алгоритмы или общие стратегии существуют для решения этих задач? Для данного n должен быть некий список, где n — самое большое число, а количество ходов, необходимых для решения головоломки, является максимальным. Как выглядит максимальная последовательность необходимого количества ходов в зависимости от n? Как выглядят самые «сложные» головоломки? Есть ли способ определить это без брутфорса?


Пользователь HackerNews под никнеймом Someone удачно описал физическую модель игры. Возьмите палочки длиной от 1 до n. Поместите некоторое их подмножество подряд в «жёлоб для решения», остальное — в «неиспользуемый жёлоб». Теперь варианты следующие: заменить две соседние палочки в «жёлобе для решения» на одну неиспользуемую палочку той же длины из «неиспользуемого жёлоба» или же заменить одну палочку в «жёлобе для решения» любыми двумя палочками из «неиспользуемого жёлоба».

Сумма элементов списка остается постоянной; следовательно, то же самое происходит с суммой недостающих элементов (палочек в «неиспользуемом жёлобе»).

Этот инвариант полезен в некоторых доказательствах, приведённых ниже; в частности, обратите внимание, что невозможно разделить элемент a, если сумма палочек в «неиспользуемом жёлобе» меньше a.

Если для некого исходного списка сумма неиспользуемых элементов меньше, чем n – 1, то ни n – 1, ни n не могут быть разделены; следовательно, они не могут поменяться местами, а значит, список будет неразрешимым.

В целом кажется целесообразным классифицировать возможные исходные положения по их наибольшему значению n и исходной длине k. Например, в случае с (10 3 5) наибольшее значение равно 10, а длина — 3.

Томаш Рокицки уже провел некоторое исследование и OEIS-тификацию. OEIS A372008 предлагает наихудшее количество ходов, необходимое для решения любого разрешимого списка с наибольшим значением n. Его записи — это максимумы каждой строки треугольника M(n, k), записи которого указывают на наихудшее число ходов для решения любого разрешимого списка с наибольшим значением n и длиной k.

(Записи с суффиксом ? получены от Томаша Рокицки, но не проверялись моим более медленным кодом).

n=1:  0
n=2:  0 -
n=3:  0 - -
n=4:  0 - -  -
n=5:  0 - -  -   -
n=6:  0 6 14  6  -  -
n=7:  0 4 12 24 26  -    -
n=8:  0 4 14 32 64 74    -    -
n=9:  0 4  8 18 66 76   86    -    -
n=10: 0 4  8 14 20 88  124  126   36    -
n=11: 0 4  8 12 16 26   90? 100? 106?   -  -
n=12: 0 4  8 12 16 20?  34? 112? 128? 130? - -
n=13: 0 4  8 10 14
n=14: 0 4  8 12 16
n=15: 0 4  8 10 14
n=16: 0 4  8 12
n=17: 0 4  8 10
n=18: 0 4  8 12
n=19: 0 4  8 10
n=20: 0 4  8

Между тем, количество C(n, k) разрешимых списков с наибольшим значением n и длиной k это:

n=1:  1
n=2:  1  0
n=3:  1  0    0
n=4:  1  0    0     0
n=5:  1  0    0     0      0
n=6:  1  8   26    12      0      0
n=7:  1 12   82   294    244      0        0
n=8:  1 14  126   760   2316   1846        0         0
n=9:  1 16  168  1344   8238  31678    47164         0         0
n=10: 1 18  216  2016  15098  89078   336154    480598      2640         0
n=11: 1 20  270  2880  25200 181308  1039174?  3907420?  5673092?        0  0
n=12: 1 22  330  3960  39600 332582? 2323524? 12999906? 47886678? 67645030? 0 0
n=13: 1 24  396  5280  59400      ?        ?         ?         ?         ?  ? ? 0
n=14: 1 26  468  6864  85800      ?        ?         ?         ?         ?  ? ? ? 0
n=15: 1 28  546  8736 120120      ?        ?         ?         ?         ?  ? ? ? 0 0
n=16: 1 30  630 10920      ?      ?        ?         ?         ?         ?  ? ? ? ? 0 0
n=17: 1 32  720 13440      ?      ?        ?         ?         ?         ?  ? ? ? ? ? ? 0
n=18: 1 34  816 16320      ?      ?        ?         ?         ?         ?  ? ? ? ? ? ? ? 0
n=19: 1 36  918 19584      ?      ?        ?         ?         ?         ?  ? ? ? ? ? ? ? 0 0
n=20: 1 38 1026     ?      ?      ?        ?         ?         ?         ?  ? ? ? ? ? ? ? ? 0 0

Обратите внимание:

  • Общее количество списков (разрешимых или нет) с наибольшим значением n и длиной k составляет

  • Неизменно, C(n, 1) = 1 и M(n, 1) = 0.

  • Для n ≥ 2 у нас есть C(n, n) = 0, так как если исходный список содержит все n возможных чисел, законных ходов нет.

  • Рассмотрим список длиной k = n – 1. Только одно число a < n отсутствует в первоначальном списке; это значит, мы не сможем разделить наибольшее значение n на само себя, лишь манипулировать элементами слева и справа от n. Итак, чтобы список был разрешимым, сумма элементов слева от n должна быть равна сумме элементов справа от n. Таким образом недостающий элемент должен иметь ту же чётность, что и n(n + 1) / 2. Теперь, если n – 1 изначально находится в левой части, нам обязательно нужно разделить его и восстановить в правой части, то есть сумма недостающих чисел должна быть не менее n – 1; но это невозможно, поскольку лишь a является недостающим элементом. Итак, недостающий элемент a должен быть n – 1, и он должен иметь ту же чётность, что и n(n + 1) / 2 , чтобы мы могли разделить остаток поровну между левой и правой частями. Согласно этой логике, C(n, n – 1) заведомо равен нулю для n ∈ {11, 12, 15, 16, 19, 20...}. С другой стороны, он может быть ненулевым, например, C(10, 9) = 2640.

  • Интуитивно кажется правдоподобным, что ∀k∃m∀n > m : C(n, k) = Total(n, k).

  • Для n ≥ 7 у нас есть C(n, 2) = Total(n, 2) и M(n, 2) = 4. Доказательство от пользователя SevenNinths смотрите здесь.

  • Для n ≥ 9 у нас, кажется, есть C(n, 3) = Total(n, 3) и M(n, 3) = 8.

  • Для n ≥ 9 у нас, кажется, есть C(n, 4) = Total(n, 4); но пока M(n, 4) колеблется между 10 и 12. Будет ли оно стабилизироваться до 12 (предполагая, что ∀k∃m∀n > m : M(n, k) = 4(k – 1)), или здесь происходит что-то более сложное?

Пользователь SevenNinths приводит конструктивное доказательство того, что ∀n ≥ 7 : M(n, 2) = 4, в виде безупречного алгоритма, позволяющего перевернуть любой двухэлементный список с n ≥ 7. Интуитивно можно предположить, что надежный алгоритм должен существовать также для списков из 3, 4 и более элементов. Обратите внимание, что алгоритм SevenNinths сохраняет длину всех промежуточных списков равной 4 или меньше, даже для очень больших n. Опять же, интуитивно из этого следует, что должна существовать достаточная длина L(n, k) < n для того, чтобы каждый разрешимый список с наибольшим значением n и исходной длиной k мог быть разрешён без создания списка длиннее чем L(n,k). Предположение для L(n, k) может значительно ускорить решение брутфорсом за счёт сокращения пространства поиска.

Достаточной длиной промежуточного списка L(n, k) для разрешаемых списков с наибольшим значением n и длиной k, является:

n=1:  1
n=2:  1 -
n=3:  1 - -
n=4:  1 - - -
n=5:  1 - - - -
n=6:  1 4 4 4 - -
n=7:  1 4 5 5 5 - -
n=8:  1 4 5 6 7 7 - -
n=9:  1 4 5 7 7 8 8 - -
n=10: 1 4 5 7 8 9 9 9 9 -
n=11: 1 4 5 7 8 9 ? ? ? - -
n=12: 1 4 5 6 8 ? ? ? ? ? - -
n=13: 1 4 5 7 8 ? ? ? ? ? ? ? -
n=14: 1 4 5 6 7 ? ? ? ? ? ? ? ? -
n=15: 1 4 5 7 8 ? ? ? ? ? ? ? ? - -
n=16: 1 4 5 6 ? ? ? ? ? ? ? ? ? ? - -
n=17: 1 4 5 7 ? ? ? ? ? ? ? ? ? ? ? ? -
n=18: 1 4 5 6 ? ? ? ? ? ? ? ? ? ? ? ? ? -
n=19: 1 4 5 7 ? ? ? ? ? ? ? ? ? ? ? ? ? - -
n=20: 1 4 5 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - -

Код C++17, на котором созданы таблицы, доступен здесь.

Tags:
Hubs:
Total votes 15: ↑15 and ↓0+19
Comments12

Articles

Information

Website
myoffice.ru
Registered
Founded
2013
Employees
1,001–5,000 employees
Location
Россия
Representative
МойОфис