Давайте определим процесс дробления массива чисел. В раздавленном состоянии мы читаем массив слева направо. Если в какой-то момент мы встречаем два одинаковых элемента подряд, мы удаляем первый и удваиваем второй. Например, вот процесс дробления следующего массива
[5,2,2,3]
^
[5,2,2,3]
^
[5,2,2,3]
^
[5,4,3]
^
[5,4,3]
^
Один и тот же элемент может быть свернут несколько раз, например [1,1,2]
становится [4]
при раздавливании.
Мы назовем массив нерушимым, когда процесс его уничтожения не изменится. Например [1,2,3]
, все еще [1,2,3]
после того, как раздавлен.
Ваша задача - взять массив и определить количество дроблений, необходимое для того, чтобы сделать его неразрушимым. Вам нужно только поддерживать целые числа в диапазоне от 0 до 2 32 -1
Это код-гольф, поэтому ответы будут оцениваться в байтах, причем меньше байтов будет лучше.
Тестовые случаи
[1] -> 0
[1,1] -> 1
[2,1,1] -> 2
[4,2,1,1] -> 3
[2,2,2,1,1] -> 3
[0,0,0,0] -> 1
[4,0,0,0,4] -> 1
[4,0,0,0,0,4] -> 1
[] -> 0
источник
[1,1,2,4,8]
вернуть 1 или 4?0,0,0,0
только1
. Это может быть идея явно упомянуть где-то, что мы подсчитываем количество раз, которое мы должны циклически проходить по массиву, чтобы полностью его раздавить, а не , как я изначально думал, общее количество раз, когда мы раздавливаем 2 числа вместе.Ответы:
сборка x86 (64-битная),
6665 байтСтроковые инструкции были полезны. Необходимость исправления отдельных ошибок в 64-разрядной среде не была.
Полностью комментируемый исходный код:
Я могу попробовать сделать это в 32-битной версии, хотя бы для развлечения, так как эти префиксы REX действительно убили меня.
Редактировать: сбрил один байт, заменив lodsq на add,% rdx на% rax и свернув два cld в один.
источник
Pyth , 22 байта
Проверьте все тестовые случаи.
источник
Haskell , 66 байт
Попробуйте онлайн!
объяснение
f
это функция, которая разбивает список Он выполняет раздавить, как описано в вопросе.g
это функция, которая считает количество давлений Еслиf x==x
, вg x=0
противном случаеg x=1+g(f x)
.источник
g(f x)
наg$f x
+
имеет более высокий приоритет, чем$
Paradoc (v0.2.10), 16 байт (CP-1252)
Попробуйте онлайн! / с верхним / нижним колонтитулом, который проверяет все контрольные примеры
Принимает список в стеке и приводит к числу в стеке.
Довольно простая реализация, если честно. Разбивает список, начиная с часового -1, просматривая список, нажимая на каждый элемент и добавляя его к элементу под ним, если они равны. В конце мы обрезаем -1. Мы только сжимаем равные числа вместе, и все числа задачи неотрицательны, так что часовой -1 не повлияет на процесс дробления. С реализованным дроблением, это всего лишь вопрос подсчета итераций до фиксированной точки.
Объяснение:
Если бы мы могли предположить, что входные данные были непустыми, нам не понадобился бы часовой и мы могли бы сбрить 2 байта:
{(\ε=k+x}]}IL(
Еще один забавный факт: мы теряем только 2 байта, если заставляем себя использовать только ASCII:
{1m\{=k+x}e]1>}IL(
источник
JavaScript (ES6), 86 байт
Неуправляемый и объясненный
тесты
Показать фрагмент кода
источник
a.length>n
так же, какa[n]!=[]._
. В этом случае (поскольку все элементы в массиве являются числами, большими чем -1), это то же самое, что иa[n]>-1
. Кроме того, такa[i]==a[++i]&&x
же, какa[i]-a[++i]||x
.1/a[i]
также работает, чтобы сохранить еще один байт.JavaScript, 67 байт
Попробуйте онлайн!
источник
Brain-Flak , 144 байта
Попробуйте онлайн!
объяснение
Функция дробления оценивает количество пар предметов, которые были раздроблены вместе:
источник
Java 8, 120 байт
Лямбда из
List<Long>
вInteger
. Входной список должен реализовыватьremove(int)
(напримерArrayList
). ПрисвоитьFunction<List<Long>, Integer>
.Попробуйте онлайн
Неуправляемая лямбда
c
подсчитывает количество дроблений до сих пор,i
является индексом в списке иf
указывает, следует ли продолжать дробление списка после завершения итерации. Внутри петель сравнивается каждая соседняя пара.i
увеличивается безоговорочно, поэтому, если элемент удаляется путем дробления,i
сначала уменьшается, чтобы отменить приращение. Прежний элемент удаляется из списка.Подтверждения
источник
valueOf
кеш. Пример:{128L, 128L}
. Это из-за тогоl.get(i)==l.get(i-1)
, что следует заменить наl.get(i).equals(l.get(i-1))
.l.get(i)-l.get(i-1)==0
сработает. Благодарность!Perl 5 , 96 байт
94 код, 2 для
-pa
Попробуйте онлайн!
источник
JavaScript (ES6), 70 байт
Объяснение:
Тестовые случаи:
Показать фрагмент кода
источник
Python 2 ,
112110108107105100 байтРедактировать: сохранено 2 байта путем удаления
or
в операторе возвратаРедактировать: сохранил 2 байта, имея
i
в качестве индекса второго из двух элементов, к которым осуществляется доступРедактировать: сохранено 1 байт благодаря @ Mr.Xcoder
Редактировать: 7 байтов сохранено благодаря @jferard
Попробуйте онлайн!
источник
JavaScript (ES6), 83 байта
Объяснение: элементы рекурсивно извлекаются из исходного массива и к ним добавляются уникальные значения, в
b
то времяc
как флаг указывает, был ли массив успешно разбит.источник
J 54 байта
Попробуйте онлайн!
Не мой лучший гольф в любом случае. Конечно, должен быть лучший способ преобразования списка с одним элементом в атом.
объяснение
раздавить
Это сокрушает массив один раз. Массив нужно задавать в обратном порядке, поскольку вставка J работает справа налево (то, что я узнал сегодня). Это не имеет особого значения, поскольку все, что нам нужно для вывода, это количество раз, которое мы можем раздавить массив.
раз
Это довольно просто: применять дробление к массиву до тех пор, пока наши результаты не сойдутся, но есть несколько проблем, с которыми мне пришлось столкнуться, что привело к гораздо большему количеству кода, чем я ожидал.
Во-первых, когда дробление сводится к одному элементу, этот элемент фактически находится в списке из одного элемента (то есть он неатомарный), поэтому функция применяется снова, что приводит к перерасчету. Чтобы исправить это, я использовал хак, который придумал, чтобы уменьшить список из одного элемента до атома, который есть
".@":
(преобразовать в строку, а затем вычислить).Во-вторых,
crush
ошибки в пустом списке. Я думаю, что вы можете определить, как должна вести себя функция при получении пустого ввода с помощью insert (/
), но я не смог ничего найти после беглого просмотра, поэтому я использую другой обходной путь. Этот обходной путь заключается в добавлении_
(бесконечности) к списку, поскольку он никогда не повлияет на число раз, когда массив будет раздавлен (_ > 2^64
). Однако , это приводит в одном списке элементов , состоящий из_
когда дается пустой список, так что нам нужно преобразовать к атому снова перед дроблением.источник
Желе , 21 байт
Попробуйте онлайн!
источник
R , 142 байта
Ужасно, я уверен, что есть более умный путь.
R целые числа на самом деле все самое большее
2^31-1
.Попробуйте онлайн!
источник