2048-подобный сдвиг массива

80

Предположим, мы хотим сместить массив, как это делается в игре 2048 : если у нас есть два равных последовательных элемента в массиве, объедините их в два элемента значения. Shift должен возвращать новый массив, где каждая пара последовательных равных элементов заменяется их суммой, и пары не должны пересекаться. Сдвиг выполняется только один раз, поэтому нам не нужно снова объединять полученные значения. Обратите внимание, что если у нас есть 3 последовательных равных элемента, мы должны суммировать самые правые элементы, поэтому, например, [2, 2, 2]должно стать [2, 4], а не [4, 2].

Задача состоит в том, чтобы написать кратчайшую функцию, которая принимает массив и возвращает сдвинутый массив.

Вы можете предположить, что все целые числа будут строго положительными.

Примеры:

[] -> []
[2, 2, 4, 4] -> [4, 8]
[2, 2, 2, 4, 4, 8] -> [2, 4, 8, 8]
[2, 2, 2, 2] -> [4, 4]
[4, 4, 2, 8, 8, 2] -> [8, 2, 16, 2]
[1024, 1024, 512, 512, 256, 256] -> [2048, 1024, 512]
[3, 3, 3, 1, 1, 7, 5, 5, 5, 5] -> [3, 6, 2, 7, 10, 10]

Я также очень заинтересован в решении с использованием Reduce :)

greenwolf
источник
11
Это очень хороший первый вызов. Добро пожаловать на сайт!
DJMcMayhem
1
Входные данные не обязательно сортируются, а числа больше нуля, что является единственным ограничением для чисел. Я думаю, что мы можем позволить наибольшему значению вписаться в стандартные границы int32. Пустой массив дает пустой массив в результате. Спасибо за участие, ценю это :)
greenwolf
3
Для тех, кто все еще голосует за закрытие как неясное, задача сводится к следующему: предположим, у вас есть массив натуральных чисел. Пройдите через это от начала до конца. Если текущий элемент равен следующему, замените его на сумму обоих и перейдите к элементу после замены, затем выполните эту проверку еще раз для этого элемента и для следующего. Повторяйте, пока не будет достигнуто начало массива.
user2428118
1
@Titus "Обратите внимание, что если у нас есть 3 последовательных равных элемента, мы должны суммировать самые правые, поэтому, например, [2, 2, 2] должно стать [2, 4], а не [4, 2]."
Мартин Эндер
1
Решение по пустым массивам вызывает сожаление; это лишило законной силы несколько ответов, включая мой собственный.
Деннис

Ответы:

19

Haskell, 47 57 50 байт

e#l|a:b<-l,e==a= -2*a:b|1<2=e:l
map abs.foldr(#)[]

Использует reduce(или, foldкак это называется в Haskell, здесь правостороннее foldr). Пример использования: map abs.foldr(#)[] $ [2,2,2,4,4,8]-> [2,4,8,8].

Изменить: +10 байт, чтобы он работал и для несортированных массивов. Объединенные числа вставляются как отрицательные значения, чтобы предотвратить повторное объединение. Они исправлены финалом map abs.

Ними
источник
Уловка с негативами действительно хороша!
xnor
14

Brain-Flak , 158 96

{({}<>)<>}<>{(({}<>)<><(({})<<>({}<>)>)>)({}[{}]<(())>){((<{}{}>))}{}{{}(<({}{})>)}{}({}<>)<>}<>

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

Объяснение:

1 Перевернуть список (переместить все в другой стек, но это не имеет значения)

{({}<>)<>}<>
{        }   #keep moving numbers until you hit the 0s from an empty stack
 ({}<>)      #pop a number and push it on the other stack
       <>    #go back to the original stack
          <> #after everything has moved, switch stacks

2 Выполните шаги 3-6, пока в этом стеке ничего не останется:

{                                                                                         }

3 Дублируйте два верхних элемента (2 3 -> 2 3 2 3)

(({}<>)<><(({})<<>({}<>)>)>)

(({}<>)<>                   #put the top number on the other stack and back on the very top
         <(({})             #put the next number on top after:
               <<>({}<>)>   #copying the original top number back to the first stack
                         )>)

4 Поместите 1 сверху, если два верхних равны, в противном случае 0 (из вики)

({}[{}]<(())>){((<{}{}>))}{}

5 Если верхние два были равны (ненулевые сверху), добавьте следующие два и нажмите результат

{{}(<({}{})>)}{}
{            }   #skip this if there is a 0 on top
 {}              #pop the 1
   (<      >)    #push a 0 after:
     ({}{})      #pop 2 numbers, add them together and push them back on 
              {} #pop off the 0

6 Переместите верхний элемент в другой стек

({}<>)<>

7 Переключитесь на другой стек и печатайте неявно

<>
Райли
источник
Пожалуйста, добавьте запятую после имени языка, в противном случае это нарушит список лидеров: P
ASCII-only
9

PHP, 116 байт

<?$r=[];for($c=count($a=$_GET[a]);$c-=$x;)array_unshift($r,(1+($x=$a[--$c]==$a[$c-1]))*$a[$c]);echo json_encode($r);

или же

<?$r=[];for($c=count($a=$_GET[a]);$c--;)$r[]=$a[$c]==$a[$c-1]?2*$a[$c--]:$a[$c];echo json_encode(array_reverse($r));

-4 байта, если выходные данные могут быть массивом print_rвместо 'json_encode`

176 байт, чтобы решить это с помощью регулярного выражения

echo preg_replace_callback("#(\d+)(,\\1)+#",function($m){if(($c=substr_count($m[0],$m[1]))%2)$r=$m[1];$r.=str_repeat(",".$m[1]*2,$c/2);return trim($r,",");},join(",",$_GET[a]));
Йорг Хюльсерманн
источник
1
Вы не можете использовать сортировку, так как результат не всегда сортируется: [4, 4, 2, 8, 8, 2] -> [8, 2, 16, 2]
Crypto
@Crypto Вы сразу после добавления новых тестов. До использования сортировки было нормально
Йорг Хюльсерманн
for($i=count($a=$argv);--$i;)$b[]=($a[$i]==$a[$i-1])?2*$a[$i--]:$a[$i];print_r(array_reverse($b));та же идея, но короче
Crypto
@Crypto Я не уверен насчет вывода в виде строкового представления или массива. для TestCase []мне нужно $r=[];Спасибо за вашу помощь
Йорг Hülsermann
9

GNU sed, 41 38 37

Включает +1 для -r
-3 благодаря цифровой травме
-1 благодаря сешумаре

:
s,(.*)(1+) \2\b,\1!\2\2!,
t
y,!, ,

Вход и выход - это строки, разделенные пробелом, в унарном порядке ( на основе этого консенсуса ).

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

Райли
источник
Используйте y,!, ,для сохранения 1 байта.
Сешумара
@seshoumara Дух ... Почему я не думал об этом. Спасибо!
Райли
8

Сетчатка , 32

\d+
$*
r`\b\1 (1+)\b
$1$1
1+
$.&

rв строке 3 активирует сопоставление регулярных выражений справа налево. А это означает, что \1ссылка должна находиться перед группой (1+)захвата, на которую она ссылается.

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

Цифровая травма
источник
Хорошо .. Этот вариант выбора справа налево очень удобен! Это часть регулярного выражения .Net или функция Retina?
Дада
Я как раз собирался опубликовать мой в 26, используя разделение перевода строки в качестве входного формата: retina.tryitonline.net/… основная экономия исходит от этого и использования транслитерации, чтобы избавиться от второй замены.
Мартин Эндер
@Dada. Это особенность .NET (и она используется под капотом для включения произвольной длины). У Retina пока нет уникальных функций регулярных выражений (хотя есть некоторые уникальные функции замещения).
Мартин Эндер
1
@MartinEnder Хорошо, спасибо! .NET регулярные выражения действительно хороши! замечен ревнивый кодер perl
Dada
@MartinEnder I Ваше решение достаточно отличается, чтобы оправдать другой ответ
Digital Trauma
8

Perl, 41 байт

Включает +1 для -p

Задайте последовательность ввода в STDIN:

shift2048.pl <<< "2 2 2 4 4 8 2"

shift2048.pl:

#!/usr/bin/perl -p
s/.*\K\b(\d+) \1\b/2*$1.A/e&&redo;y/A//d
Тон Хоспел
источник
8

Python, 61 байт

def f(l):b=l[-2:-1]==l[-1:];return l and f(l[:~b])+[l[-1]<<b]

Логическое значение bпроверяет, должны ли последние два элемента разрушаться, проверяя, чтобы они были равны, таким образом, что это безопасно для списков длиной 1 или 0. Последний элемент затем добавляется с множителем 1для равных или 2для неравных. Он добавляется к рекурсивному результату в списке с множеством элементов, отрубленных до конца. Спасибо Деннису за 1 байт!

XNOR
источник
[l[-1]<<b]сохраняет байт.
Деннис
l[-2:-1]это[l[-2]]
mbomb007
2
Мне нужно, чтобы он работал для списков размером 0 и 1.
xnor
7

Perl, 43 + 1 ( -p) = 44 байта

Тон Хоспел придумал ответ в 41 байт , зацените!

-4 спасибо @Ton Hospel!

Редактировать : добавлено \b, так как без него происходил сбой при вводе, как 24 4при выводе 28.

$_=reverse reverse=~s/(\b\d+) \1\b/$1*2/rge

Запустить с -pфлагом:

perl -pe '$_=reverse reverse=~s/(\b\d+) \1\b/$1*2/rge' <<< "2 2 2 4 4"


Я не вижу другого способа, кроме как использовать reverseдвойное сгибание вправо (так же, как сгибание s/(\d+) \1/$1*2/geвлево, т. 2 2 2Е. Становление 4 2вместо 2 4). Итак, 14 байтов потеряно благодаря reverse... Тем не менее, я думаю, что должен быть другой (лучший) способ (в конце концов, это perl!), Дайте мне знать, если найдете его!

папа
источник
reverse reverseкажется немного длинным Я не специалист по Perl, но есть ли способ, которым вы можете сделать ярлык reverse(если не использовать [ab] eval)?
Cyoce
Хороший сексегер. Обратите внимание, что вы можете просто пропустить($_)
Тон Хоспел
@TonHospel спасибо. Действительно, документ reverseвыглядит так, что reverseего нельзя вызвать без аргумента (хорошо, примеры показывают, что это может быть, но есть только один прототип:) reverse LIST, поэтому я забыл $_, что являюсь аргументом по умолчанию;)
Дада
А LISTможет быть пустым ...
Тон Хоспел
@TonHospel действительно, но обычно, когда оператор использует в $_качестве аргумента по умолчанию, в документе указывается прототип без параметров (например, printили lenght...). Или, может быть, у меня просто неправильное впечатление.
Дада
7

JavaScript (ES6), 68 байт

f=a=>a.reduceRight((p,c)=>(t=p[0],p.splice(0,c==t,c==t?c+t:c),p),[])
    
console.log([
  [],
  [2, 2, 4, 4],
  [2, 2, 2, 4, 4, 8],
  [2, 2, 2, 2],
  [4, 4, 2, 8, 8, 2],
  [1024, 1024, 512, 512, 256, 256],
  [3, 3, 3, 1, 1, 7, 5, 5, 5, 5],
].map(f))

Сундар
источник
2
Неплохо, но согласно выполненному фрагменту: [1024, 1024, 512, 512, 256, 256]разрешается как [2048, 512, 1024]и нет [2048, 1024, 512]...?
WallyWest
7

Perl 5,10, 61 50 байт ( 49 + 1 для флага)

Спасибо Ton Hospel за сохранение 11 байтов!

Решение без регулярных выражений, с -aфлагом:

@a=($F[-1]-$b?$b:2*pop@F,@a)while$b=pop@F;say"@a"

Попробуй здесь!

Пол Пикард
источник
Хороший альтернативный метод. Жаль, что массивы почти всегда проигрывают строкам в perl. Тем не менее, вы можете стать немного ближе, играя в гольф свой код @a=($F[-1]-$b?$b:2*pop@F,@a)while$b=pop@F;say"@a"(50 байтов)
Тон Хоспел
@TonHospel Действительно, я стараюсь избегать решений на основе строк (просто чтобы показать, что Perl может сделать больше, чем это!). Я все равно не играю, чтобы выиграть: D Спасибо за советы по игре в гольф!
Пол Пикард
7

JavaScript (ES6), 68 65 58 57 65 64 байта

Сохранено 1 байт благодаря @ l4m2

Исправлено для несортированных массивов теперь, когда выяснено, что такие входные данные следует ожидать.

f=(a,l=[],m)=>(x=a.pop())*!m-l?f(a,x).concat(l):x?f(a,2*x,1):[l]

console.log(f([2, 2, 4, 4]));
console.log(f([2, 2, 2, 4, 4, 8]));
console.log(f([2, 2, 2, 2]));
console.log(f([4, 2, 2]));

Arnauld
источник
1
Я собирался предложить редактирование, которое вы только что сделали :)
ETHproductions
a=>(a.reverse()+'').replace(/(.),\1/g,(c,i)=>i*2).split`,`.reverse()?
14 м2,
@ l4m2 Это работает для однозначных входов, но не сработает [1024, 1024, 512, 512, 256, 256](я думаю, что этот тестовый пример, возможно, был добавлен позже).
Арно
@Arnauld Ну, твои тоже терпят неудачу ...
l4m2
f=(a,l=[],m)=>(x=a.pop())*!m-l?f(a,x).concat(l):x?f(a,2*x,1):[l]?
l4m2
6

05AB1E , 26 байт

D¥__X¸«DgL*ê¥X¸«£vy2ôO})í˜

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

Обобщенные шаги

  1. Уменьшить путем вычитания, чтобы найти различия между последовательными элементами
  2. Сократить путем вычитания над индексами этих мест, чтобы найти длину последовательных элементов
  3. Разделить ввод на куски этой длины
  4. Разделить куски на пары
  5. Сумма каждой пары
  6. Переверните каждый суммированный кусок
  7. Свести в одномерный список
Emigna
источник
5

Mathematica, 53 байта

Join@@(Reverse[Plus@@@#~Partition~UpTo@2]&/@Split@#)&

объяснение

Split@#

Разбейте ввод на подсписки, состоящие из прогонов идентичных элементов. то есть {2, 2, 2, 4, 8, 8}становится {{2, 2, 2}, {4}, {8, 8}}.

#~Partition~UpTo@2

Partition каждый из подсписка в длину разделов больше 2. т.е. {{2, 2, 2}, {4}, {8, 8}}становится {{{2, 2}, {2}}, {{4}}, {{8, 8}}}.

Plus@@@

Итого по каждому разделу. то есть {{{2, 2}, {2}}, {{4}}, {{8, 8}}}становится {{4, 2}, {4}, {16}}.

Reverse

Отмените результаты, потому что Partitionкоманда Mathematica идет слева направо, но мы хотим, чтобы разделы были в другом направлении. то есть {{4, 2}, {4}, {16}}становится {{2, 4}, {4}, {16}}.

Join@@

Сгладить результат. то есть {{2, 4}, {4}, {16}}становится {2, 4, 4, 16}.

Юнг Хван Мин
источник
Привет, ДХМ! Спасибо за ответ. Я не очень хорошо понимаю Mathematica, поэтому не могли бы вы немного объяснить, что происходит?
Исаак
Plus@@@есть , Tr/@и я думаю , что вы можете избежать круглые скобки и Join@@если вы используете ##&@@на результат Reverse(не проверял , хотя).
Мартин Эндер
5

Java 7, 133 байта

Object f(java.util.ArrayList<Long>a){for(int i=a.size();i-->1;)if(a.get(i)==a.get(i-1)){a.remove(i--);a.set(i,a.get(i)*2);}return a;}

Ввод представляет собой ArrayList, и он просто возвращается назад, удаляя и удваивая при необходимости.

Object f(java.util.ArrayList<Long>a){
    for(int i=a.size();i-->1;)
        if(a.get(i)==a.get(i-1)){
            a.remove(i--);
            a.set(i,a.get(i)*2);
        }
    return a;
}
Geobits
источник
Вы сравниваете Longссылки в строке 3 с ==. Посмотрим a.get(i)-a.get(i-1)==0.
Якоб
4

Perl, 37 байт

Включает +4 для -0n

Запустите с вводом в виде отдельных строк на STDIN:

perl -M5.010 shift2048.pl
2
2
2
4
4
8
2
^D

shift2048.pl:

#!/usr/bin/perl -0n
s/\b(\d+
)(\1|)$//&&do$0|say$1+$2
Тон Хоспел
источник
4

Haskell, 56 байт

g(a:b:r)|a==b=a+b:g r|l<-b:r=a:g l
g x=x
r=reverse
r.g.r
Damien
источник
4

PHP, 86 100 99 94 байта

for($r=[];$v=+($p=array_pop)($a=&$argv);)array_unshift($r,end($a)-$v?$v:2*$p($a));print_r($r);

требует PHP 7.0; принимает значения из аргументов командной строки.

Запустите -nrили попробуйте онлайн .

Titus
источник
2
[2, 2, 2] возвращает [4,2] вместо [2,4]
Crypto
for($r=[];$v=($p=array_pop)($a=&$_GET[a]);)array_unshift($r,end($a)-$v?$v:2*$p($a));print_r($r);на 1 байт короче
Йорг Хюльсерманн
3

Юлия 205 байт

t(x)=Val{x}
s(x)=t(x)()
f^::t(1)=f
^{y}(f,::t(y))=x->f(((f^s(y-1))(x)))
g()=[]
g{a}(::t(a))=[a]
g{a}(::t(a),B...)=[a;g(B...)]
g{a}(::t(a),::t(a),B...)=[2a;g(B...)]
K(A)=g(s.(A)...)
H(A)=(K^s(length(A)))(A)

Функция для вызова H

например H([1,2,2,4,8,2,])

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

  • t(a) является типом значения, представляющим значение (a).
  • s(a) является экземпляром этого типа значения
  • gэто функция, которая отправляет значения разности (используя типы значений) и номера своих параметров. И это круто
  • Kпросто оборачивает gтак что

Очень крутая часть:

f^::t(1)=f
^{y}(f,::t(y))=x->f(((f^s(y-1))(x)))

Это определяет ^оператор для применения к функциям. Так что K^s(2)(X)такое же , как K(K(X)) так Hпросто вызывают Kна Kкуче раз - достаточное количество раз , чтобы , конечно , разрушатся любой вложенный случай

Это можно сделать намного короче, но так просто весело.

Линдон Уайт
источник
3

PowerShell v2 +, 81 байт

param($n)($b=$n[$n.count..0]-join','-replace'(\d+),\1','($1*2)'|iex)[$b.count..0]

Принимает входные данные в виде явного массива $n, переворачивает его $n[$n.count..0], -joinэлементы вместе с запятой, затем регулярное выражение -replaceсовпадает с парой соответствующих цифр с первым элементом, a *2, и заключено в скобки. Трубы, которые в результате (которые для ввода @(2,2,4,4)будут выглядеть (4*2),(2*2)) переходят к iex(сокращенно Invoke-Expressionи аналогично eval), что преобразует умножение в фактические числа. Сохраняет результирующий массив в $b, инкапсулирует его в parens, чтобы поместить его в конвейер, а затем переворачивает $bс [$b.count..0]. Оставляет полученные элементы в конвейере, а вывод неявным.


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

NB-- В PowerShell концепция «возврата» пустого массива не имеет смысла - он преобразуется в тот момент,$nullкогда он покидает область видимости - и поэтому он эквивалентен возврату ничего, что и делается в первом примере (после некоторых злых многословных ошибок). Кроме того, выходные данные здесь разделены пробелами, так как это разделитель по умолчанию для строковых массивов.

PS C:\Tools\Scripts\golfing> @(),@(2,2,4,4),@(2,2,2,4,4,8),@(2,2,2,2),@(4,4,2,8,8,2),@(1024,1024,512,512,256,256),@(3,3,3,1,1,7,5,5,5,5)|%{"$_ --> "+(.\2048-like-array-shift.ps1 $_)}
Invoke-Expression : Cannot bind argument to parameter 'Command' because it is an empty string.
At C:\Tools\Scripts\golfing\2048-like-array-shift.ps1:7 char:67
+   param($n)($b=$n[$n.count..0]-join','-replace'(\d+),\1','($1*2)'|iex)[$b.count. ...
+                                                                   ~~~
    + CategoryInfo          : InvalidData: (:String) [Invoke-Expression], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.InvokeExpressionCommand

Cannot index into a null array.
At C:\Tools\Scripts\golfing\2048-like-array-shift.ps1:7 char:13
+   param($n)($b=$n[$n.count..0]-join','-replace'(\d+),\1','($1*2)'|iex)[$b.count. ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

 --> 
2 2 4 4 --> 4 8
2 2 2 4 4 8 --> 2 4 8 8
2 2 2 2 --> 4 4
4 4 2 8 8 2 --> 8 2 16 2
1024 1024 512 512 256 256 --> 2048 1024 512
3 3 3 1 1 7 5 5 5 5 --> 3 6 2 7 10 10
AdmBorkBork
источник
3

Javascript - 103 байта

v=a=>{l=a.length-1;for(i=0;i<l;i++)a[l-i]==a[l-1-i]?(a[l-i-1]=a[l-i]*2,a.splice(l-i,1)):a=a;return a}
Alexis_A
источник
Сохранено 16 байтов благодаря подсказкам @MayorMonty на этой странице
Alexis_A
Это не работает Тестирование с [2,2,4,4]выходами [2,2,4,4].
Конор О'Брайен
1
Ага. Узел v6.2.1
Конор О'Брайен
Мой плохой .. Я запускал его с другим кодом JS в том же файле, и глобальные переменные перепутались.
Alexis_A
3

Brain-Flak , 60 байт

{({}<>)<>}<>{(({}<>)<>[({})]){((<{}>))}{}{({}<>{})(<>)}{}}<>

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

Объяснение:

{({}<>)<>}<>   Reverse stack

{   While input exists
  (
    ({}<>)   Push copy of last element to the other stack
    <>[({})] And subtract a copy of the next element
  )   Push the difference
  {   If the difference is not 0
    ((<{}>)) Push two zeroes
  }{}  Pop a zero
  {   If the next element is not zero, i.e the identical element
    ({}<>{})  Add the element to the copy of the previous element
    (<>)      Push a zero
  }{}    Pop the zero
}<>  End loop and switch to output stack
Джо Кинг
источник
2

Юлия, 73 82 байта

f(l)=l==[]?[]:foldr((x,y)->y[]==x?vcat(2x,y[2:end]):vcat(x,y),[l[end]],l[1:end-1])

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

Если заголовок текущего списка не равен следующему элементу, который нужно добавить, просто добавьте его.

В противном случае удалите заголовок списка (звучит жестоко) и добавьте элемент раз 2.

пример

f([3,3,3,1,1,7,5,5,5,5]) 
returns a new list:
[3,6,2,7,10,10]
nyro_0
источник
2

Ракетка 166 байт

(λ(l)(let g((l(reverse l))(o '()))(cond[(null? l)o][(=(length l)1)(cons(car l)o)]
[(=(car l)(second l))(g(drop l 2)(cons(* 2(car l))o))][(g(cdr l)(cons(car l)o))])))

Ungolfed:

(define f
  (λ (lst)
    (let loop ((lst (reverse lst)) 
               (nl '()))
      (cond                            ; conditions: 
        [(null? lst)                   ; original list empty, return new list;
               nl]
        [(= (length lst) 1)            ; single item left, add it to new list
              (cons (first lst) nl)]
        [(= (first lst) (second lst))  ; first & second items equal, add double to new list
              (loop (drop lst 2) 
                    (cons (* 2 (first lst)) nl))]
        [else                          ; else just move first item to new list
              (loop (drop lst 1) 
                    (cons (first lst) nl))]  
        ))))

Тестирование:

(f '[])
(f '[2 2 4 4]) 
(f '[2 2 2 4 4 8]) 
(f '[2 2 2 2]) 
(f '[4 4 2 8 8 2])
(f '[1024 1024 512 512 256 256]) 
(f '[3 3 3 1 1 7 5 5 5 5])
(f '[3 3 3 1 1 7 5 5 5 5 5])

Выход:

'()
'(4 8)
'(2 4 8 8)
'(4 4)
'(8 2 16 2)
'(2048 1024 512)
'(3 6 2 7 10 10)
'(3 6 2 7 5 10 10)
rnso
источник
1

Japt , 12 байт

ò¦ ®ò2n)mxÃc

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

Распаковано и как это работает

Uò!= mZ{Zò2n)mx} c

Uò!=    Partition the input array where two adjacent values are different
        i.e. Split into arrays of equal values
mZ{     Map the following function...
Zò2n)     Split into arrays of length 2, counting from the end
          e.g. [2,2,2,2,2] => [[2], [2,2], [2,2]]
mx        Map `Array.sum` over it
}
c       Flatten the result

Получил некоторую идею от решения Jonathan Allan's Jelly .

фонтанчик для питья
источник
0

Mathematica, 51 байт

Abs[#//.{Longest@a___,x_/;x>0,x_,b___}:>{a,-2x,b}]&

{Longest@a___,x_/;x>0,x_,b___}сопоставляет список, содержащий два последовательных идентичных положительных числа, и преобразует эти два числа в -2x. Longestзаставляет спички происходить как можно позже.

Процесс иллюстрируется пошагово:

   {3, 3, 3, 1, 1, 7, 5, 5, 5, 5}
-> {3, 3, 3, 1, 1, 7, 5, 5, -10}
-> {3, 3, 3, 1, 1, 7, -10, -10}
-> {3, 3, 3, -2, 7, -10, -10}
-> {3, -6, -2, 7, -10, -10}
-> {3, 6, 2, 7, 10, 10}
njpipeorgan
источник
0

Vim, 28 байт

G@='?\v(\d+)\n\1<C-@>DJ@"<C-A>-@=<C-@>'<CR>

Макрос, который regex ищет в обратном порядке для поиска последовательных чисел и складывает их вместе.

Входной массив должен быть один номер в строке. Этот формат спасает меня от ударов, и это хорошо, но настоящая причина в том, чтобы обходить совпадения с регулярными выражениями. Учитывая строку 222, если вы /22будете соответствовать только первой паре, а не перекрывающей второй паре. Правила перекрытия отличаются, когда две пары начинаются на разных строках. В этом вызове [2, 2, 2]становится [2, 4], так что соответствие перекрывающейся пары имеет решающее значение.

ПРИМЕЧАНИЕ. Для задания требовался только один проход. По этой причине вам нужно иметь :set nowrapscan. С помощью :set wrapscanя мог бы сделать версию, которая заканчивает работу за несколько проходов, хотя это решение, как написано, не всегда делает это.

  • <C-@>: Обычно в командной строке для ввода литерала <CR>без запуска команды вы должны его экранировать <C-V>. Но вы можете напечатать <C-@>unescaped, и он будет рассматриваться как <C-J>/ <NL>, что будет похоже на <CR>запуск макроса, но не на ввод текста. Попробуйте прочитать :help NL-used-for-Nul.
  • @=: В этот раз я не могу легко использовать записанный макрос, потому что есть вероятность, что на входе нет подходящих пар. Если это произойдет во время выполнения макроса, неудачный поиск приведет к сбою макроса. Но если это произойдет во время (неявного первого) прохода записи, остальные команды обычного режима будут запущены, повредив файл. Недостатком @=является то, что я теряю байт при рекурсивном вызове; иногда вы можете использовать его @@как рекурсивный вызов, но @"в этом случае он будет выполняться на 4 байта раньше.
  • DJ@"<C-A>-: DJудаляет строку и помещает число (без новой строки) в регистр, поэтому я могу запустить его как макрос для числового аргумента to <C-A>. Я должен -потом, чтобы я не получил второй матч в таких случаях, как [4, 2, 2].
udioica
источник
0

Perl6, 92 байта

{my @b;loop ($_=@^a-1;$_>=0;--$_) {@b.unshift($_&&@a[$_]==@a[$_-1]??2*@a[$_--]!!@a[$_])};@b}
bb94
источник