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


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:



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.


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

<>

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

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


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.


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

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!


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


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


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!


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


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

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


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

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

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

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 .


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.


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

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}

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


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]

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)

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 .


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}

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

0

Perl6, 92 bytes

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.