Cambio de matriz similar a 2048

80

Supongamos que queremos cambiar una matriz como se hace en el juego 2048 : si tenemos dos elementos consecutivos iguales en la matriz, fusionarlos en el doble del elemento de valor. Shift debe devolver una nueva matriz, donde cada par de elementos iguales consecutivos se reemplaza con su suma, y ​​los pares no deben cruzarse. El cambio se realiza solo una vez, por lo que no necesitamos fusionar los valores resultantes nuevamente. Tenga en cuenta que si tenemos 3 elementos iguales consecutivos, tenemos que sumar los que están más a la derecha, por lo que, por ejemplo, [2, 2, 2]debería convertirse [2, 4], no [4, 2].

La tarea es escribir la función más corta que toma una matriz y devuelve una matriz desplazada.

Puede suponer que todos los enteros serán estrictamente positivos.

Ejemplos:

[] -> []
[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]

También estoy muy interesado en la solución usando reduce :)

Greenwolf
fuente
11
Este es un primer desafío muy agradable. Bienvenido al sitio!
DJMcMayhem
1
La entrada no está necesariamente ordenada y los números son mayores que cero, esa es la única restricción en los números. Creo que podemos permitir que el valor más grande se ajuste a los límites estándar int32. Una matriz vacía da una matriz vacía como resultado. Gracias por la participación, aprecio eso :)
greenwolf
3
Para aquellos que todavía votan para cerrar como confusos, el desafío esencialmente se reduce a esto: supongamos que tienen una serie de enteros positivos. Camina a través de él de principio a fin. Si el elemento actual es igual al siguiente, reemplácelo con la suma de ambos y muévase al elemento después del reemplazo, luego realice esta verificación nuevamente para ese elemento y el siguiente. Repita hasta llegar al comienzo de la matriz.
user2428118
1
@Titus "Tenga en cuenta que si tenemos 3 elementos iguales consecutivos, tenemos que sumar los más a la derecha, por lo que, por ejemplo, [2, 2, 2] debería convertirse en [2, 4], no en [4, 2]".
Martin Ender
1
La decisión sobre matrices vacías es desafortunada; ha invalidado algunas respuestas, incluida la mía.
Dennis

Respuestas:

21

Jalea , 10 9 8 bytes

Œg+2/€UF

TryItOnline o ejecuta todos los casos de prueba

¿Cómo?

Œg+2/€UF - Main link: a                 e.g. [2,2,2,4,4,8]
Œg       - group runs of equal elements      [[2,2,2],[4,4],[8]]
   2/€   - pairwise reduce for each with
  +      -     addition                      [[4,2],[8],[8]]
      U  - reverse (vectorises)              [[2,4],[8],[8]]
       F - flatten list                      [2,4,8,8]
Jonathan Allan
fuente
19

Haskell, 47 57 50 bytes

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

Usos reduce(o foldcomo se le llama en Haskell, aquí un pliegue derecho foldr). Ejemplo de uso: map abs.foldr(#)[] $ [2,2,2,4,4,8]-> [2,4,8,8].

Editar: +10 bytes para que funcione también para matrices sin clasificar. Los números combinados se insertan como valores negativos para evitar una segunda fusión. Se corrigen por una final map abs.

nimi
fuente
¡El truco con los negativos es realmente bueno!
xnor
14

Brain-Flak , 158 96

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

Pruébalo en línea!

Explicación:

1 Invierta la lista (mover todo a la otra pila, pero eso no importa)

{({}<>)<>}<>
{        }   #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 Siga los pasos 3-6 hasta que no quede nada en esta pila:

{                                                                                         }

3 Duplicar los dos elementos superiores (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 Pon un 1 en la parte superior si los dos primeros son iguales, un 0 en caso contrario (de la wiki)

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

5 Si los dos primeros eran iguales (distintos de cero en el superior) agregue los dos siguientes y presione el resultado

{{}(<({}{})>)}{}
{            }   #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 Mueva el elemento superior a la otra pila

({}<>)<>

7 Cambie a la otra pila e imprima implícitamente

<>
Riley
fuente
pls agrega una coma después del nombre del idioma, de lo contrario se rompe ty de la tabla de clasificación: P
Solo ASCII
9

PHP, 116 bytes

<?$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);

o

<?$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 Bytes si la salida puede ser una matriz en print_rlugar de 'json_encode`

176 bytes para resolver esto con una expresión regular

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]));
Jörg Hülsermann
fuente
1
No se puede usar la ordenación ya que el resultado no siempre se ordena: [4, 4, 2, 8, 8, 2] -> [8, 2, 16, 2]
Cripto
@Crypto Estás justo después de que se hayan agregado los nuevos casos de prueba. Antes de que el uso de sort estuviera bien
Jörg Hülsermann
for($i=count($a=$argv);--$i;)$b[]=($a[$i]==$a[$i-1])?2*$a[$i--]:$a[$i];print_r(array_reverse($b));misma idea pero más corta
Crypto
@Crypto No estoy seguro acerca de la salida como representación de cadena o una matriz. para el caso de prueba []que necesito $r=[];Gracias por su ayuda
Jörg Hülsermann
9

GNU sed, 41 38 37

Incluye +1 para -r
-3 Gracias a Digital Trauma
-1 Gracias a seshoumara

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

La entrada y la salida son cadenas separadas por espacios en unario ( según este consenso ).

Pruébalo en línea!

Riley
fuente
Use y,!, ,para guardar 1 byte.
seshoumara
@seshoumara Duh ... ¿Por qué no pensé en eso? ¡Gracias!
Riley
8

Retina , 32

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

ren la línea 3 activa la coincidencia de expresiones regulares de derecha a izquierda. Y esto significa que la \1referencia debe venir antes del (1+)grupo de captura al que hace referencia.

Pruébalo en línea.

Trauma digital
fuente
Bien ... ¡Esa opción de derecha a izquierda para combinar es bastante útil! ¿Es parte de .Net regex o una función Retina?
Dada
Estaba a punto de publicar el mío a los 26 años, usando la separación de salto de línea como formato de entrada: retina.tryitonline.net/... los principales ahorros provienen de eso y el uso de la transliteración para deshacerse de la segunda sustitución.
Martin Ender
@Dada Es una característica .NET (y se usa debajo del capó para permitir mirar hacia atrás de longitud arbitraria). Retina aún no tiene características únicas de expresiones regulares (aunque tiene algunas características de sustitución únicas).
Martin Ender
1
@MartinEnder Ok, gracias! ¡Las expresiones regulares de .NET son realmente geniales! codificador perl celoso visto
Dada
@MartinEnder I su solución es lo suficientemente diferente como para justificar otra respuesta
Digital Trauma
8

Perl, 41 bytes

Incluye +1 para -p

Dar secuencia de entrada en 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
Ton Hospel
fuente
8

Python, 61 bytes

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

El booleano bverifica si los dos últimos elementos deberían colapsar comprobando que son iguales de una manera segura para las listas de longitud 1 o 0. El último elemento si se agrega con un multiplicador de 1para igual o 2para desigual. Se agrega al resultado recursivo en la lista con tantos elementos cortados al final. ¡Gracias a Dennis por 1 byte!

xnor
fuente
[l[-1]<<b]Guarda un byte.
Dennis
l[-2:-1]es[l[-2]]
mbomb007
2
Necesito que funcione para listas de tamaño 0 y 1.
xnor
7

Perl, 43 + 1 ( -p) = 44 bytes

A Ton Hospel se le ocurrió una respuesta de 41 bytes , ¡compruébalo!

-4 gracias a @Ton Hospel!

Editar : agregado \b, ya que sin él estaba fallando en la entrada como 24 4en la que habría sido la salida 28.

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

Corre con -pbandera:

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


No veo otra manera que usar reversedos veces para doblar a la derecha (como solo s/(\d+) \1/$1*2/gese doblaría a la izquierda, es decir, 2 2 2se convertiría en 4 2lugar de 2 4). Entonces 14 bytes perdidos gracias a reverse... Aún así, creo que debe haber otra (mejor) forma (¡es perl después de todo!), ¡Avíseme si lo encuentra!

Dada
fuente
reverse reverseParece un poco largo. No soy un experto en Perl, pero ¿hay alguna manera de que puedas hacer un atajo reverse(si no es nada, [ab] usando eval)?
Cyoce
Buen sexeger. Aviso que sólo puede dejar de lado el($_)
Ton Hospel
@TonHospel gracias. De hecho, el documento de reverseapariencia reverseno se puede invocar sin argumento (bueno, los ejemplos muestran que puede ser, pero solo hay un prototipo:) reverse LIST, así que olvidé $_ser el argumento predeterminado;)
Dada
A LISTpuede estar vacío ...
Ton Hospel
@TonHospel de hecho, pero generalmente cuando un operador usa $_como argumento predeterminado, el documento especifica un prototipo sin parámetros (como printo lenght...). O tal vez esa es solo una impresión equivocada que tengo.
Dada
7

JavaScript (ES6), 68 bytes

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))

Sundar
fuente
2
No está mal, pero de acuerdo con el fragmento ejecutado: ¿se [1024, 1024, 512, 512, 256, 256]está resolviendo como [2048, 512, 1024]y no [2048, 1024, 512]...?
WallyWest
7

Perl 5.10, 61 50 bytes ( 49 + 1 para bandera)

¡Gracias a Ton Hospel por guardar 11 bytes!

Solución libre de expresiones regulares, con -abandera:

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

¡Intenta aquí!

Paul Picard
fuente
Buen método alternativo. Las matrices de lástima casi siempre pierden las cadenas en perl. Aún así, puede acercarse un poco más jugando golf su código a @a=($F[-1]-$b?$b:2*pop@F,@a)while$b=pop@F;say"@a"(50 bytes)
Ton Hospel
@TonHospel De hecho, tiendo a evitar soluciones basadas en cadenas (¡solo para mostrar que Perl puede hacer más que eso!). No juego para ganar de todos modos: D ¡Gracias por los consejos de golf!
Paul Picard
7

JavaScript (ES6), 68 65 58 57 65 64 bytes

Guardado 1 byte gracias a @ l4m2

Se corrigió para las matrices sin clasificar ahora que se ha aclarado que tales entradas son de esperar.

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
fuente
1
Estaba a punto de sugerir la edición que acaba de hacer :)
ETHproductions
a=>(a.reverse()+'').replace(/(.),\1/g,(c,i)=>i*2).split`,`.reverse()?
l4m2
@ l4m2 Eso funciona para entradas de un solo dígito, pero fallaría [1024, 1024, 512, 512, 256, 256](creo que este caso de prueba puede haberse agregado más tarde).
Arnauld
@Arnauld Bueno, el tuyo también falla ...
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 bytes

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

Pruébalo en línea!

Pasos generalizados

  1. Reduzca por sustracción para encontrar dónde difieren los elementos consecutivos
  2. Reduzca por sustracción sobre los índices de esos lugares para encontrar la longitud de elementos consecutivos
  3. Dividir la entrada en trozos de esas longitudes
  4. Dividir trozos en pares
  5. Suma cada par
  6. Invierta cada trozo sumado
  7. Acoplar a lista unidimensional
Emigna
fuente
5

Mathematica, 53 bytes

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

Explicación

Split@#

Divida la entrada en sublistas que consisten en corridas de elementos idénticos. es decir se {2, 2, 2, 4, 8, 8}convierte {{2, 2, 2}, {4}, {8, 8}}.

#~Partition~UpTo@2

Particione cada una de las sublistas en particiones de longitud como máximo 2. es decir, se {{2, 2, 2}, {4}, {8, 8}}convierte {{{2, 2}, {2}}, {{4}}, {{8, 8}}}.

Plus@@@

Total de cada partición. es decir se {{{2, 2}, {2}}, {{4}}, {{8, 8}}}convierte {{4, 2}, {4}, {16}}.

Reverse

Invierta los resultados porque el Partitioncomando de Mathematica va de izquierda a derecha, pero queremos que las particiones estén en otra dirección. es decir se {{4, 2}, {4}, {16}}convierte {{2, 4}, {4}, {16}}.

Join@@

Aplane el resultado. es decir se {{2, 4}, {4}, {16}}convierte {2, 4, 4, 16}.

JungHwan Min
fuente
Hola jhm Gracias por la respuesta. No entiendo muy bien Mathematica, ¿podría agregar un poco de explicación sobre lo que está pasando?
isaacg
Plus@@@es Tr/@y creo que puedes evitar los paréntesis y Join@@si lo usas ##&@@en el resultado de Reverse(sin embargo, no lo he probado).
Martin Ender
5

Java 7, 133 bytes

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;}

Input es una ArrayList, y simplemente se repite, eliminando y duplicando donde sea necesario.

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
fuente
Estás comparando Longreferencias en la línea 3 con ==. Considere a.get(i)-a.get(i-1)==0.
Jakob
4

Perl, 37 bytes

Incluye +4 para -0n

Ejecute con la entrada como líneas separadas en 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
Ton Hospel
fuente
4

Haskell, 56 bytes

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
fuente
4

PHP, 86100 99 94 bytes

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

requiere PHP 7.0; toma valores de los argumentos de la línea de comandos.

Ejecutar -nro probarlo en línea .

Titus
fuente
2
[2, 2, 2] devuelve [4,2] en lugar de [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);es 1 Byte más corto
Jörg Hülsermann
3

Julia 205 bytes

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)

La función a llamar es H

p.ej H([1,2,2,4,8,2,])

Esta no es la manera más corta de hacerlo en julia. Pero es tan genial, que quería compartirlo de todos modos.

  • t(a) es un tipo de valor, que representa el valor (a).
  • s(a) es una instancia de ese tipo de valor
  • ges una función que distribuye los valores de diferencia (usando los tipos de valor) y los números de sus parámetros. Y eso es genial
  • Ksimplemente envuelve gpara que

Parte extra genial:

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

Esto define el ^operador para aplicar a las funciones. De manera que K^s(2)(X)es igual que K(K(X)) lo que Hse acaba de llamar Ka Kun montón de veces - sin duda suficientes veces como para colapsar cualquier caso anidada

Esto se puede hacer mucho más corto, pero de esta manera es muy divertido.

Lyndon White
fuente
3

PowerShell v2 +, 81 bytes

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

Toma la entrada como una matriz explícita $n, la invierte $n[$n.count..0], -joinjunta los elementos con una coma, luego regexifica -replaceun par de dígitos coincidentes con el primer elemento, a *2, y está rodeado por pares. Tuberías que resultan (que @(2,2,4,4)se verá como entrada (4*2),(2*2)) a iex(abreviatura Invoke-Expressiony similar a eval), que convierte la multiplicación en números reales. Almacena la matriz resultante en $b, encapsula eso en parens para colocarlo en la tubería, luego invierte $bcon [$b.count..0]. Deja los elementos resultantes en la tubería, y la salida es implícita.


Casos de prueba

NB: en PowerShell, el concepto de "devolver" una matriz vacía no tiene sentido, se convierte en$nulltan pronto como sale del alcance, por lo que es el equivalente a no devolver nada, que es lo que se hace aquí en el primer ejemplo (después de algunos errores malvadamente verbosos). Además, la salida aquí está separada por espacios, ya que es el separador predeterminado para las matrices en cadena.

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
fuente
3

Javascript - 103 bytes

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
fuente
Ahorré 16 bytes gracias a los consejos de @MayorMonty en esta página
Alexis_A
Esto no funciona Pruebas con [2,2,4,4]rendimientos [2,2,4,4].
Conor O'Brien
1
Sip. Nodo v6.2.1
Conor O'Brien
Lo malo ... Lo estaba ejecutando con otro código JS en el mismo archivo y las variables globales se confundieron.
Alexis_A
3

Brain-Flak , 60 bytes

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

Pruébalo en línea!

Explicación:

{({}<>)<>}<>   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
Jo King
fuente
2

Python 2, 94 bytes

def f(a,r=[]):
 while a:
    if len(a)>1and a[-1]==a[-2]:a.pop();a[-1]*=2
    r=[a.pop()]+r
 print r

Pruébalo en línea

mbomb007
fuente
2

Julia, 73 82 bytes

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

Use el pliegue derecho para construir la lista de atrás hacia adelante (también se puede usar doblar a la izquierda e invertir la lista al principio y al final).

Si el encabezado de la lista actual no es igual al siguiente elemento a anteponer, simplemente añádalo.

De lo contrario, elimine el encabezado de la lista (suena un poco cruel) y anteponga el elemento por 2.

Ejemplo

f([3,3,3,1,1,7,5,5,5,5]) 
returns a new list:
[3,6,2,7,10,10]
nyro_0
fuente
2

Raqueta 166 bytes

(λ(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))])))

Sin golf:

(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))]  
        ))))

Pruebas:

(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])

Salida:

'()
'(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
fuente
1

Japt , 12 bytes

ò¦ ®ò2n)mxÃc

Pruébalo en línea!

Desempaquetado y cómo funciona

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

Tengo una idea de la solución Jelly de Jonathan Allan .

Bubbler
fuente
0

Mathematica, 51 bytes

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

{Longest@a___,x_/;x>0,x_,b___}coincide con una lista que contiene dos números positivos idénticos consecutivos y transforma estos dos números en -2x. Longestobliga a los partidos a suceder lo más tarde posible.

El proceso se ilustra paso a paso:

   {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
fuente
0

Vim, 28 bytes

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

Una macro que regex busca hacia atrás para buscar números consecutivos y los agrega.

La matriz de entrada debe ser un número por línea. Este formato me ahorra trazos, lo cual es bueno, pero la verdadera razón es evitar coincidencias de expresiones regulares superpuestas. Dada la cadena 222, si /22solo coincidirá con el primer par, no con el segundo par superpuesto. Las reglas de superposición son diferentes cuando los dos pares comienzan en líneas diferentes. En este desafío se [2, 2, 2]hace [2, 4], por lo que emparejar el par superpuesto es crítico.

NOTA: El desafío solo requería un solo pase. Por esa razón, necesitas tener :set nowrapscan. Con :set wrapscanpodría hacer una versión que termine el trabajo en múltiples pases, aunque esta solución tal como está escrita no siempre lo hará.

  • <C-@>: Normalmente, en una línea de comando, para escribir un literal <CR>sin ejecutar el comando con el que tendría que escapar <C-V>. Pero puede escribir <C-@>sin escape y se tratará como un <C-J>/ <NL>, que será como <CR>cuando ejecuta la macro pero no cuando está escribiendo. Intenta leer :help NL-used-for-Nul.
  • @=: No puedo usar una macro grabada fácilmente esta vez porque existe la posibilidad de que la entrada no tenga pares coincidentes. Si eso sucede mientras se ejecuta una macro, la búsqueda fallida fallará en la macro. Pero si sucede durante el pase de grabación (primero implícito), el resto de los comandos del modo normal se ejecutarán, dañando el archivo. La desventaja @=es que pierdo un byte en la llamada recursiva; a veces se puede usar @@como una llamada recursiva, pero eso se ejecutaría @"desde 4 bytes anteriormente en este caso.
  • DJ@"<C-A>-: DJelimina la línea y coloca el número (sin nueva línea) en un registro, para que pueda ejecutarlo como una macro para un argumento de número <C-A>. Tengo que hacerlo -después para no tener un segundo partido en casos como [4, 2, 2].
udioica
fuente
0

Perl6, 92 bytes

{my @b;loop ($_=@^a-1;$_>=0;--$_) {@b.unshift($_&&@a[$_]==@a[$_-1]??2*@a[$_--]!!@a[$_])};@b}
bb94
fuente