Растянуть массив


13

Ранее я определил процесс дробления массива

В раздавленном состоянии мы читаем массив слева направо. Если в какой-то момент мы встречаем два одинаковых элемента подряд, мы удаляем первый и удваиваем второй.

Например, вот процесс дробления следующего массива

[5,2,2,4]
 ^
[5,2,2,4]
   ^
[5,2,2,4]
     ^
[5,4,4]
   ^
[5,4,4]
     ^
[5,8]
   ^

Обратите внимание, что один и тот же элемент может быть свернут несколько раз. В примере 2,2,4был свернут в 8один проход.

Теперь дробить массивы легко, а трудно их дробить. Ваша задача - взять массив положительных целых чисел в качестве входных данных и вывести наибольший массив, который может сформировать входные данные при неоднократном дроблении. Например, массив [4]образован дроблением, [2,2]который, в свою очередь, образован дроблением [1,1,1,1]. Так как мы не можем иметь нецелые значения[1,1,1,1] может быть мы не можем больше их раздавить, и поэтому наш ответ.

Вы никогда не получите 0входной массив, потому что такие массивы могут быть расширены до бесконечности. Вы также никогда не получите случай с двумя одинаковыми нечетными числами рядом друг с другом, такие случаи не могут быть результатом дробления.

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

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

Тестовые случаи

[] -> []
[5] -> [5]
[6] -> [3,3]
[8] -> [1,1,1,1,1,1,1,1]
[4,8] -> [1,1,1,1,1,1,1,1,1,1,2]
[2,8] -> [1, 1, 1, 1, 2, 1, 1, 1, 1]
[4,4] -> [1,1,1,1,1,1,1,1]

1
Извините, но я все еще не понимаю правила. зачем [1,1,1,1,1,1,1,1,1,1,2]производить [4, 8]вместо [8, 4]? это должно быть [1,>1,1,1,1,1,1,1,1,1,2], [2,1,>1,1,1,1,1,1,1,2], [2,>2,1,1,1,1,1,1,2], [4,1,>1,1,1,1,1,2], [4,2,1,>1,1,1,2], [4,2,>2,1,1,2], [4,>4,1,1,2], [8,1,>1,2], [8,2,>2], [8,4]?
TSH

2
@tsh Я думаю, у тебя неправильное представление о том, как работает дробление. Вот путь он принимает первый пароль: [1,>1,1,1,1,1,1,1,1,1,2], [2,>1,1,1,1,1,1,1,1,2], [2,1,>1,1,1,1,1,1,1,2], [2,2,>1,1,1,1,1,1,2], [2,2,1,>1,1,1,1,1,2], [2,2,2,>1,1,1,1,2], [2,2,2,1,>1,1,1,2], [2,2,2,2,>1,1,2], [2,2,2,2,1,>1,2], [2,2,2,2,2,>2], [2,2,2,2,4>], второй проход: [2,>2,2,2,4],[4,>2,2,4] , [4,2,>2,4], [4,4,>4], [4,8>]. Надеюсь, это прояснит ситуацию. Если вы хотите, чтобы какой-то код смотрел на предыдущий вопрос, есть ответы, которые реализуют функцию дробления.
Пост Рок Гарф Хантер

Это нормально, если я выведу числа, каждое из которых разделено новой строкой?
Скоттинет

@scottinet Это разумный способ вывести список. Преуспевать.
Пост Рок Гарф Хантер

Тестовый пример [4, 4]должен быть удален, так как мы никогда не сможем получить этот массив после последовательности stretch => crush, так как это закончится[8]
scottinet

Ответы:


2

JavaScript (Node.js) , 237 221 213 186 байт

f=a=>a.map(b=>{for(i=1;~b%2;b/=2)i*=2;return Array(i).fill(b)}).reduce((t,c,i,s)=>{b=c.slice();if(i)r=2*s[--i].length,b.length>=r&&b[0]==s[i][0]?b[r-2]+=b.pop():b;return t.concat(b)},[])

Попробуйте онлайн!

Этот алгоритм вычисляет оптимальные растянутые массивы, растягивая каждое число до максимума, а затем, если необходимо, он сжимает пару чисел в нужном месте, эффективно создавая «блокировщик дробления», прерывая последовательность дробления предыдущего числа.

Например:

[1, 1, 1, 1, 1, 1]дает [4,2]один раз раздавлен, но [1, 1, 1, 1, 2]приводит к[2, 4]

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

  • Блокатор раздавливания необходимо размещать только в том случае, если предыдущее растянутое число равно текущему, и если текущая растянутая последовательность больше, чем предыдущая. Например,[2, 4] требуется блокиратор раздавливания (растянутое число 1повторяется и [1, 1]короче [1,1,1,1]), но [4, 2]и [2, 6]не требуется
  • если мы вызываем nпредыдущую растянутую последовательность и если вышеуказанное условие проверяется, то текущая последовательность является повторением nпоследовательности. Чтобы прервать последовательность дробления предыдущего числа, нам нужно поместить блокатор раздавливания в конце второй nпоследовательности текущего числа, чтобы растянуть. Пример: [2, 8] => [(1, 1)=n, (1, 1) + (2) + (1, 1) + ...]или[4, 8] => [(1, 1, 1, 1)=n, (1, 1, 1, 1) + (1, 1, 2) + ...]


1

Python 2 , 230 228 226 байт

Работает путем итерации всех возможных списков с той же суммой, что и входной. Удаляя те, которые не равны входному массиву в каком-то раздавленном состоянии, выбираем самый длинный.

Изменить: -2 байта, удалив ifв основной функции

Изменить: -2 байта, удалив две ненужные квадратные скобки

lambda x:max((c(z[:],x),len(z),z)for z in b(sum(x)))[2]
def c(x,y):
 i=e=1
 while x[i:]:
	if x[~-i]==x[i]:del x[i];i-=1;x[i]*=2;e=2
	i+=1
 return x==y or~-e and c(x,y)
b=lambda s:[z+[-~i]for i in range(s)for z in b(s+~i)]+[[]]

Попробуйте онлайн!

объяснение

Основная функция, отвечающая за поиск всех возможных решений и выбор самого длинного

lambda x:max((c(z[:],x),len(z),z)for z in b(sum(x)))[2]

Функция дробления, которая проверяет, равен ли y одному из дроблений.

def c(x,y):
 i=e=1
 while x[i:]:
	if x[~-i]==x[i]:del x[i];i-=1;x[i]*=2;e=2
	i+=1
 return x==y or~-e and c(x,y)

Генерация всех возможных перестановок с заданной суммой

b=lambda s:[z+[-~i]for i in range(s)for z in b(s+~i)]+[[]]

0

05AB1E , 41 37 байт

vy[DÉ#2÷]DYQX©NoDU‹&sDV¸X∍sić·®·Íǝ}»,

Попробуйте онлайн!

Порт моего решения Javascript.

Пояснения:

vy                   for each member of the list
[DÉ#2÷]              divide by 2 until odd: stack = stretched value, N = iterations
DYQ                  stetched value equal to the previous one?
X©NoDU‹              previous size < current one? (+store the new size in X)
&                    AND on the 2 previous tests
sDV¸X∍s              build a list of the new stretched value repeated X times
                      (+store the new stetched value in Y)
ić·®·Íǝ}             if the previous tests are true:
                       reduce the result list size by 1
                       multiply by 2 the number at the crush block position
»,                   join by newline + print the list
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.