Mudança de matriz tipo 2048

80

Suponha que queremos mudar uma matriz como é feita no jogo de 2048 : se tivermos dois elementos consecutivos iguais na matriz, mescle-os com o dobro do elemento de valor. Shift deve retornar uma nova matriz, onde cada par de elementos iguais consecutivos é substituído por sua soma e os pares não devem se cruzar. A troca é realizada apenas uma vez, portanto, não precisamos mesclar os valores resultantes novamente. Observe que, se tivermos 3 elementos iguais consecutivos, temos que somar os elementos mais à direita, portanto, por exemplo, [2, 2, 2]deve se tornar [2, 4], não [4, 2].

A tarefa é escrever a função mais curta que pega uma matriz e retorna uma matriz deslocada.

Você pode assumir que todos os números inteiros serão estritamente positivos.

Exemplos:

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

Também estou muito interessado em solução usando o reduzir :)

lobo verde
fonte
11
Este é um primeiro desafio muito bom. Bem vindo ao site!
DJMcMayhem
1
A entrada não é necessariamente classificada e os números são maiores que zero, que é a única restrição aos números. Podemos deixar o maior valor se encaixar nos limites int32 padrão, eu acho. A matriz vazia fornece a matriz vazia como resultado. Obrigado pela participação, apreciar que :)
greenwolf
3
Para aqueles que ainda votam para fechar como obscuros, o desafio se resume a isso: suponha que você tenha uma matriz de números inteiros positivos. Caminhe por ele do fim ao começo. Se o elemento atual for igual ao próximo, substitua-o pela soma de ambos e vá para o elemento após a substituição e execute essa verificação novamente para esse elemento e para o próximo. Repita até o início da matriz ser atingido.
user2428118
1
@Titus "Observe que, se tivermos 3 elementos iguais consecutivos, temos que somar os elementos mais à direita; por exemplo, [2, 2, 2] deve se tornar [2, 4], não [4, 2]".
Martin Ender
1
A decisão sobre matrizes vazias é lamentável; invalidou algumas respostas, incluindo as minhas.
Dennis #

Respostas:

21

Geléia , 10 9 8 bytes

Œg+2/€UF

TryItOnline ou execute todos os casos de teste

Quão?

Œ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
fonte
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(ou foldcomo é chamado em Haskell, aqui à direita foldr). Exemplo de uso: map abs.foldr(#)[] $ [2,2,2,4,4,8]-> [2,4,8,8].

Editar: +10 bytes para fazê-lo funcionar também com matrizes não classificadas. Os números mesclados são inseridos como valores negativos para impedir uma segunda mesclagem. Eles são corrigidos por uma final map abs.

nimi
fonte
O truque com negativos é muito bom!
Xnor #
14

Flacidez Cerebral , 158 96

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

Experimente online!

Explicação:

1 Inverta a lista (movendo tudo para a outra pilha, mas isso não 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 Execute as etapas 3 a 6 até não sobrar mais nada nesta pilha:

{                                                                                         }

3 Duplique os dois principais elementos (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 Coloque um 1 em cima, se os dois primeiros forem iguais, e 0 em caso contrário (do wiki)

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

5 Se os dois primeiros forem iguais (diferente de zero no topo), adicione os próximos dois e pressione o 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 Mova o elemento superior para a outra pilha

({}<>)<>

7 Alterne para a outra pilha e imprima implicitamente

<>
Riley
fonte
pls adiciona vírgula após o nome do idioma, caso contrário, quebra o cabeçalho ty: P
ASCII-only
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);

ou

<?$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 se a saída puder ser uma matriz em print_rvez de 'json_encode`

176 bytes para resolver isso com um Regex

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
fonte
1
Você não pode usar a classificação, pois o resultado nem sempre é classificado: [4, 4, 2, 8, 8, 2] -> [8, 2, 16, 2]
Crypto
@Crypto Você está certo após a adição de novos casos de teste. Antes do uso de tipo estava bem
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));mesma idéia, mas mais curta
Crypto
@ Crpto Não tenho certeza sobre a saída como representação de string ou uma matriz. para o testcase []eu preciso $r=[];Obrigado por sua ajuda
Jörg Hülsermann
9

GNU sed, 41 38 37

Inclui +1 por -r
-3 Agradecimentos ao trauma digital
-1 Agradecimentos a seshoumara

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

Entrada e saída são cadeias separadas por espaço em unárias (com base nesse consenso ).

Experimente online!

Riley
fonte
Use y,!, ,para salvar 1 byte.
precisa saber é o seguinte
@seshoumara Duh ... Por que eu não pensei nisso. Obrigado!
Riley
8

Retina , 32

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

rna linha 3 ativa a correspondência de regex da direita para a esquerda. E isso significa que a \1referência precisa vir antes do (1+)grupo de captura ao qual faz referência.

Experimente online.

Trauma Digital
fonte
Bom .. Essa opção da direita para a esquerda para combinar é bastante útil! Faz parte do .net regex ou do recurso Retina?
Dada
Eu estava prestes a publicar o meu aos 26 anos, usando a separação de alimentação de linha como formato de entrada: retina.tryitonline.net/… as principais economias advêm disso e usando a transliteração para se livrar da segunda substituição.
Martin Ender
@Dada É um recurso .NET (e é usado sob o capô para permitir olhares de comprimento arbitrário). O Retina ainda não possui recursos exclusivos de regex (embora tenha alguns recursos exclusivos de substituição).
Martin Ender
1
@MartinEnder Ok thanks! Regex do .NET são realmente ótimos! ciumento perl coder descoberto
Dada
@MartinEnder I a sua solução é diferente o suficiente para justificar uma outra resposta
Trauma Digital
8

Perl, 41 bytes

Inclui +1 para -p

Dê a sequência de entrada no 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
fonte
8

Python, 61 bytes

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

O booleano bverifica se os dois últimos elementos devem entrar em colapso, verificando se são iguais de uma maneira que seja segura para listas de comprimento 1 ou 0. O último elemento se anexado a um multiplicador de 1para igual ou 2para desigual. É anexado ao resultado recursivo da lista com tantos elementos cortados no final. Agradecimentos a Dennis por 1 byte!

xnor
fonte
[l[-1]<<b]salva um byte.
Dennis
l[-2:-1]é[l[-2]]
mbomb007
2
Eu preciso que ele funcione para listas de tamanho 0 e 1. #
7115
7

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

Ton Hospel surgiu com 41 bytes de resposta , confira!

-4 graças a @Ton Hospel!

Edit : adicionado \b, pois sem ele estava falhando na entrada como 24 4na qual a saída teria sido 28.

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

Corra com a -pbandeira:

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


Não vejo outra maneira do que usar reverseduas vezes para dobrar à direita (como s/(\d+) \1/$1*2/gefaria com a esquerda, ou seja 2 2 2, ao 4 2invés de 2 4). Então, 14 bytes perdidos graças a reverse... Ainda acho que deve haver outra maneira (melhor) (afinal, é perl!), Deixe-me saber se você a encontra!

dada
fonte
reverse reverseparece um pouco demorado. Eu não sou especialista em Perl, mas existe uma maneira de criar um atalho para reverse(se nada mais, [ab] usar eval)?
Cyoce
Sexeger agradável. Note que você pode simplesmente deixar de fora o($_)
Ton Hospel 6/16
@TonHospel thanks. Na verdade, o doc de reverseolhares como reversenão pode ser chamado sem argumento (assim os exemplos mostram que pode ser, mas não é apenas um protótipo: reverse LIST), então eu esqueci $_de ser o argumento padrão;)
Dada
Um LISTpode estar vazio ...
Ton Hospel
@TonHospel, de fato, mas geralmente quando um operador usa $_como argumento padrão, o documento especifica um protótipo sem parâmetros (como printou lenght...). Ou talvez seja apenas uma impressão errada que tenho.
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))

pôr do sol
fonte
2
Nada mal, mas de acordo com o trecho executado: [1024, 1024, 512, 512, 256, 256]está resolvendo como [2048, 512, 1024]e não [2048, 1024, 512]...?
WallyWest 06/10
7

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

Obrigado a Ton Hospel por salvar 11 bytes!

Solução sem regex, com -abandeira:

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

Tente aqui!

Paul Picard
fonte
Bom método alternativo. Uma matriz de pena quase sempre perde para strings em perl. Ainda assim, você pode ficar um pouco mais perto de golfe seu código para @a=($F[-1]-$b?$b:2*pop@F,@a)while$b=pop@F;say"@a"(50 bytes)
Ton Hospel
@TonHospel Na verdade, costumo evitar soluções baseadas em strings (apenas para mostrar que o Perl pode fazer mais do que isso!). De qualquer forma, não jogo para ganhar: D Obrigado pelas dicas de golfe!
Paul Picard
7

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

Guardado 1 byte graças a @ l4m2

Corrigido para matrizes não classificadas agora que foi esclarecido que tais entradas são esperadas.

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
fonte
1
Eu estava prestes a sugerir a edição que você acabou de fazer :)
ETHproductions
a=>(a.reverse()+'').replace(/(.),\1/g,(c,i)=>i*2).split`,`.reverse()?
l4m2
@ l4m2 Isso funciona para entradas de um dígito, mas falharia [1024, 1024, 512, 512, 256, 256](acho que esse caso de teste pode ter sido adicionado posteriormente).
Arnauld
@Arnauld Bem, o seu também falha ...
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})í˜

Experimente online!

Etapas generalizadas

  1. Reduza por subtração para descobrir onde os elementos consecutivos diferem
  2. Reduza por subtração sobre os índices desses locais para encontrar a duração de elementos consecutivos
  3. Divida a entrada em partes com esses comprimentos
  4. Dividir pedaços em pares
  5. Soma cada par
  6. Inverta cada pedaço resumido
  7. Achatar para lista unidimensional
Emigna
fonte
5

Mathematica, 53 bytes

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

Explicação

Split@#

Divida a entrada em sublistas que consistem em execuções de elementos idênticos. ou seja, {2, 2, 2, 4, 8, 8}se torna {{2, 2, 2}, {4}, {8, 8}}.

#~Partition~UpTo@2

Particione cada uma das sub-listas em partições no máximo 2. ou seja, {{2, 2, 2}, {4}, {8, 8}}torna-se {{{2, 2}, {2}}, {{4}}, {{8, 8}}}.

Plus@@@

Total de cada partição. ou seja, {{{2, 2}, {2}}, {{4}}, {{8, 8}}}se torna {{4, 2}, {4}, {16}}.

Reverse

Inverta os resultados porque o Partitioncomando do Mathematica vai da esquerda para a direita, mas queremos que as partições estejam em outra direção. ou seja, {{4, 2}, {4}, {16}}se torna {{2, 4}, {4}, {16}}.

Join@@

Achate o resultado. ou seja, {{2, 4}, {4}, {16}}se torna {2, 4, 4, 16}.

JungHwan Min
fonte
Oi JHM! Obrigado pela resposta. Eu não entendo muito bem o Mathematica, então você poderia adicionar um pouco de explicação sobre o que está acontecendo?
Isaacg #
Plus@@@é Tr/@e acho que você pode evitar os parênteses e Join@@se usar ##&@@o resultado de Reverse(ainda não o testou).
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;}

A entrada é um ArrayList e apenas faz um loop para trás, removendo e dobrando quando necessário.

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
fonte
Você está comparando Longreferências na linha 3 com ==. Considere a.get(i)-a.get(i-1)==0.
Jakob
4

Perl, 37 bytes

Inclui +4 para -0n

Execute com a entrada como linhas separadas no 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
fonte
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
fonte
4

PHP, 86 100 99 94 bytes

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

requer PHP 7.0; recebe valores dos argumentos da linha de comando.

Corra com -nrou experimente online .

Titus
fonte
2
[2, 2, 2] retorna [4,2] em vez 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);é 1 Byte mais curto
Jörg Hülsermann 6/16
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)

A função a ser chamada é H

por exemplo H([1,2,2,4,8,2,])

Isso não é o caminho mais curto para fazer isso em julia. Mas é tão legal que eu queria compartilhar de qualquer maneira.

  • t(a) é um tipo de valor, representando o valor (a).
  • s(a) é uma instância desse tipo de valor
  • gé uma função que despacha os valores de diferença (usando os tipos de valor) e os números de seus parâmetros. E isso é legal
  • Kapenas envolve gpara que

Parte extra legal:

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

Isso define o ^operador a ser aplicado às funções. Assim que K^s(2)(X)é o mesmo que K(K(X)) assim Hé apenas chamar Kem Kum monte de vezes - vezes o suficiente para certamente desmoronar qualquer caso aninhada

Isso pode ser feito muito mais curto, mas dessa maneira é tão divertido.

Lyndon White
fonte
3

PowerShell v2 +, 81 bytes

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

Pega a entrada como uma matriz explícita $n, inverte-a $n[$n.count..0], -joins os elementos juntamente com uma vírgula e regex -replaceum par de dígitos correspondente ao primeiro elemento, a *2, e entre parênteses. Canais que resultam (com @(2,2,4,4)aparência de entrada (4*2),(2*2)) para iex(abreviado Invoke-Expressione semelhante a eval), que converte a multiplicação em números reais. Armazena a matriz resultante em $b, encapsula isso em parênteses para colocá-lo no pipeline e depois reverte $bcom [$b.count..0]. Deixa os elementos resultantes no pipeline e a saída é implícita.


Casos de teste

NB - No PowerShell, o conceito de "retornar" uma matriz vazia não faz sentido - é convertido$nullassim que sai do escopo - e, portanto, é o equivalente a não retornar nada, o que é feito aqui no primeiro exemplo. (após alguns erros perversamente detalhados). Além disso, a saída aqui é separada por espaço, pois é o separador padrão para matrizes com strings.

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
fonte
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
fonte
Guardado 16 bytes graças a @MayorMonty dicas nesta página
Alexis_A
Isso não funciona. Testando com [2,2,4,4]rendimentos [2,2,4,4].
Conor O'Brien
1
Sim. Nó v6.2.1
Conor O'Brien
Meu mal .. eu estava rodando com outro código JS no mesmo arquivo e as variáveis ​​globais se misturaram.
Alexis_A
3

Flacidez cerebral , 60 bytes

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

Experimente online!

Explicação:

{({}<>)<>}<>   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
Brincadeira
fonte
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

Experimente online

mbomb007
fonte
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 a dobra à direita para criar a lista de trás para a frente (também é possível usar a dobra para a esquerda e inverter a lista no início e no final).

Se o cabeçalho da lista atual não for igual ao próximo elemento a ser anexado, basta anexá-lo.

Caso contrário, remova o cabeçalho da lista (soa meio cruel) e acrescente o elemento 2 vezes.

Exemplo

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

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

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

Testando:

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

Resultado:

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

Japonês , 12 bytes

ò¦ ®ò2n)mxÃc

Experimente online!

Descompactado e como 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

Tenho alguma idéia da solução de Jonathan Allan's Jelly .

Bubbler
fonte
0

Mathematica, 51 bytes

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

{Longest@a___,x_/;x>0,x_,b___}corresponde a uma lista contendo dois números positivos idênticos consecutivos e transforma esses dois números em -2x. Longestforça as partidas a acontecer o mais tarde possível.

O processo é ilustrado passo a passo:

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

Vim, 28 bytes

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

Uma macro que regex pesquisa para trás em busca de números consecutivos correspondentes e os adiciona.

A matriz de entrada precisa ser um número por linha. Esse formato me economiza traços, o que é bom, mas o verdadeiro motivo é trabalhar com as correspondências de regex sobrepostas. Dada a sequência 222, se você /22corresponder apenas ao primeiro par, não ao segundo par sobreposto. As regras de sobreposição são diferentes quando os dois pares começam em linhas diferentes. Nesse desafio , [2, 2, 2]torna- [2, 4]se essencial a combinação do par sobreposto.

NOTA: O desafio pediu apenas um único passe. Por esse motivo, você precisa ter :set nowrapscan. Com :set wrapscaneu pude fazer uma versão que finalize o trabalho em várias passagens, embora essa solução como escrita nem sempre faça isso.

  • <C-@>: Normalmente, em uma linha de comando, para digitar um literal <CR>sem executar o comando com o qual você teria que escapar <C-V>. Mas você pode digitar sem <C-@>escape e ele será tratado como um <C-J>/ <NL>, que será como <CR>quando você executar a macro, mas não quando estiver digitando. Tente ler :help NL-used-for-Nul.
  • @=: Desta vez não posso usar uma macro gravada facilmente, porque existe a possibilidade de a entrada não ter pares correspondentes. Se isso acontecer durante a execução de uma macro, a pesquisa malsucedida falhará na macro. Mas se isso ocorrer durante a passagem de gravação (implícita primeiro), o restante dos comandos no modo normal será executado, danificando o arquivo. A desvantagem @=é que perco um byte na chamada recursiva; às vezes você pode usar @@como uma chamada recursiva, mas que seria executada a @"partir de 4 bytes anteriormente neste caso.
  • DJ@"<C-A>-: DJExclui a linha e coloca o número (sem nova linha) num registo, para que eu possa executá-lo como uma macro para um argumento número para <C-A>. Eu tenho que -depois para não ter uma segunda partida em casos como esse [4, 2, 2].
udioica
fonte
0

Perl6, 92 bytes

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