2048-ähnliche Arrayverschiebung


80

Angenommen, wir möchten ein Array wie im Spiel 2048 verschieben : Wenn das Array zwei gleiche aufeinanderfolgende Elemente enthält, füge sie zu dem doppelten Wertelement zusammen. Shift muss ein neues Array zurückgeben, in dem jedes Paar aufeinanderfolgender gleicher Elemente durch ihre Summe ersetzt wird und sich Paare nicht überschneiden dürfen. Die Verschiebung wird nur einmal ausgeführt, sodass die resultierenden Werte nicht erneut zusammengeführt werden müssen. Beachten Sie, dass , wenn wir drei aufeinanderfolgenden gleichen Elemente haben, müssen wir rechtesten diejenigen summieren, so zB [2, 2, 2]werden sollte [2, 4], nicht [4, 2].

Die Aufgabe besteht darin, die kürzeste Funktion zu schreiben, die ein Array aufnimmt und ein verschobenes Array zurückgibt.

Sie können davon ausgehen, dass alle ganzen Zahlen streng positiv sind.

Beispiele:

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

Ich bin auch sehr an einer Lösung mit redu interessiert :)


11
Dies ist eine sehr schöne erste Herausforderung. Willkommen auf der Seite!
DJMcMayhem

1
Die Eingabe muss nicht unbedingt sortiert sein, und Zahlen sind größer als Null. Dies ist die einzige Beschränkung für Zahlen. Ich denke, wir lassen den größten Wert in Standard-Int32-Grenzen passen. Leeres Array gibt als Ergebnis ein leeres Array aus. Vielen Dank für die Teilnahme,
danke

3
Für diejenigen, die noch als unklar stimmen, läuft die Herausforderung im Wesentlichen auf Folgendes hinaus: Angenommen, Sie haben eine Reihe positiver Ganzzahlen. Gehen Sie von Anfang bis Ende durch. Wenn das aktuelle Element gleich dem nächsten ist, ersetzen Sie es durch die Summe von beiden und gehen Sie nach dem Ersetzen zum Element. Führen Sie dann diese Überprüfung für dieses und das nächste Element erneut durch. Wiederholen Sie diesen Vorgang, bis der Anfang des Arrays erreicht ist.
user2428118

1
@Titus "Beachten Sie, dass wir, wenn wir drei aufeinanderfolgende gleiche Elemente haben, die äußersten rechten Elemente summieren müssen, sodass beispielsweise [2, 2, 2] zu [2, 4] und nicht zu [4, 2] werden sollte."
Martin Ender

1
Die Entscheidung über leere Felder ist unglücklich; Es hat einige Antworten ungültig gemacht, auch meine eigenen.
Dennis

Antworten:



19

Haskell, 47 57 50 Bytes

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

Verwendet reduce(oder foldwie es in Haskell heißt, hier eine Rechtsfalte foldr). Anwendungsbeispiel: map abs.foldr(#)[] $ [2,2,2,4,4,8]-> [2,4,8,8].

Bearbeiten: +10 Bytes, damit es auch für unsortierte Arrays funktioniert. Zusammengeführte Zahlen werden als negative Werte eingefügt, um eine zweite Zusammenführung zu verhindern. Sie werden durch ein Finale korrigiert map abs.


Der Trick mit Negativen ist wirklich schön!
xnor

14

Brain-Flak , 158 96

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

Probieren Sie es online!

Erläuterung:

1 Kehre die Liste um (verschiebe alles auf den anderen Stapel, aber das ist egal)

{({}<>)<>}<>
{        }   #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 Führen Sie die Schritte 3 bis 6 aus, bis auf diesem Stapel nichts mehr vorhanden ist:

{                                                                                         }

3 Dupliziere die beiden oberen Elemente (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 Lege eine 1 oben drauf, wenn die beiden oberen gleich sind, andernfalls eine 0 (aus dem Wiki)

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

5 Wenn die ersten beiden gleich waren (oben nicht Null), addieren Sie die nächsten beiden und drücken Sie das Ergebnis

{{}(<({}{})>)}{}
{            }   #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 Verschieben Sie das obere Element auf den anderen Stapel

({}<>)<>

7 Wechseln Sie zum anderen Stapel und drucken Sie implizit

<>

pls addieren Komma nach Sprache Namen, sonst bricht Rangliste 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);

oder

<?$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, wenn die Ausgabe ein Array print_ranstelle von "json_encode" sein kann

176 Bytes, um dies mit einem Regex zu lösen

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
Sie können sort nicht verwenden, da das Ergebnis nicht immer sortiert ist: [4, 4, 2, 8, 8, 2] -> [8, 2, 16, 2]
Crypto

@Crypto Sie haben gleich Recht, nachdem die neuen Testfälle hinzugefügt wurden. Bevor der Einsatz von sort in Ordnung war
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));gleiche Idee, aber kürzer
Crypto

@ Crypto Ich bin nicht sicher über die Ausgabe als String-Darstellung oder ein Array. Für den Testfall []brauche ich $r=[];Danke für deine Hilfe
Jörg Hülsermann


8

Retina , 32

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

rIn Zeile 3 wird der reguläre Ausdruck von rechts nach links aktiviert. Dies bedeutet, dass die \1Referenz vor der (1+)Erfassungsgruppe stehen muss, auf die sie verweist.

Probieren Sie es online aus.


Schön .. Diese Option von rechts nach links ist sehr praktisch! Ist es Teil von .Net Regex oder einer Retina-Funktion?
Dada

Ich wollte gerade meinen mit 26 veröffentlichen, wobei ich die Zeilenvorschubseparation als Eingabeformat verwendete: retina.tryitonline.net/… die Haupteinsparungen resultierten daraus, und indem ich die Transliteration verwendete, um die zweite Substitution loszuwerden.
Martin Ender

@Dada Es ist eine .NET-Funktion (und wird unter der Haube verwendet, um Lookbehinds mit beliebiger Länge zu ermöglichen). Retina hat noch keine einzigartigen regulären Ausdrücke (obwohl es einige einzigartige Substitutionsmerkmale hat).
Martin Ender

1
@MartinEnder Ok danke! .NET Regex sind wirklich toll! neidisch Perl-Coder entdeckt
Dada

@MartinEnder I Ihre Lösung ist unterschiedlich genug, um eine andere Antwort zu rechtfertigen
Digital Trauma

8

Perl, 41 Bytes

Beinhaltet +1 für -p

Geben Sie die Eingabesequenz für STDIN ein:

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]

Der Boolesche Wert büberprüft, ob die letzten beiden Elemente minimiert werden sollen, indem überprüft wird, ob sie für Listen der Länge 1 oder 0 gleich sind. Dem letzten Element wird dann ein Multiplikator 1für Gleich oder 2für Ungleich angehängt . Es wird an das rekursive Ergebnis in der Liste angehängt, wobei am Ende so viele Elemente abgeschnitten wurden. Danke an Dennis für 1 Byte!


[l[-1]<<b]Speichert ein Byte.
Dennis

l[-2:-1]ist[l[-2]]
mbomb007

2
Ich brauche es für Listen der Größe 0 und 1.
xnor

7

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

Ton Hospel hat eine Antwort von 41 Bytes gefunden , probieren Sie es aus!

-4 danke an @Ton Hospel!

Edit : hinzugefügt \b, da es ohne fehlgeschlagen wäre bei der Eingabe wie 24 4bei der Ausgabe 28.

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

Laufen mit -pFlagge:

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


Ich sehe eine andere Art und Weise nicht als mit reversezweimal nach rechts-fach (wie gerade s/(\d+) \1/$1*2/gewürde links-fache, also 2 2 2würde 4 2statt 2 4). Also 14 Bytes verloren dank reverse... Trotzdem denke ich, dass es einen anderen (besseren) Weg geben muss (es ist schließlich Perl!), Lass es mich wissen, wenn du es findest!


reverse reversescheint ein bisschen langwierig. Ich bin kein Perl-Experte, aber gibt es eine Möglichkeit, eine Verknüpfung zu erstellen reverse(wenn nichts anderes, [ab] using eval)?
Cyoce

Nette Sexegerin. Beachten Sie, dass Sie das($_)
Ton Hospel

@TonHospel danke. Tatsächlich ist die doc reversesieht aus wie reversekann nicht ohne Argument aufgerufen werden (auch die Beispiele zeigen , kann es sein, aber es ist nur ein Prototyp: reverse LIST), so vergaß ich $_das Argument Standard ist;)
Dada

A LISTkann leer sein ...
Ton Hospel

@TonHospel in der Tat, aber normalerweise, wenn ein Operator $_als Standardargument verwendet, gibt das Dokument einen Prototyp ohne Parameter (wie printoder lenght...) an. Oder vielleicht ist das nur ein falscher Eindruck, den ich habe.
Dada

7

JavaScript (ES6), 68 Byte

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
Nicht schlecht, aber laut dem ausgeführten Snippet: [1024, 1024, 512, 512, 256, 256]Wie wird aufgelöst [2048, 512, 1024]und nicht [2048, 1024, 512]...?
WallyWest

7

Perl 5.10, 61 50 Bytes ( 49 + 1 für Flag)

Vielen Dank an Ton Hospel für das Speichern von 11 Bytes!

Regex-freie Lösung mit -aFlagge:

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

Versuch es hier!


Schöne alternative Methode. Schade, dass Arrays in Perl fast immer gegen Strings verlieren. Sie können jedoch noch ein bisschen näher heranrücken, indem Sie Ihren Code auf @a=($F[-1]-$b?$b:2*pop@F,@a)while$b=pop@F;say"@a"(50 Byte)
Ton Hospel,

@TonHospel In der Tat neige ich dazu, stringbasierte Lösungen zu vermeiden (nur um zu zeigen, dass Perl mehr kann als das!). Ich spiele sowieso nicht um zu gewinnen: D Danke für die Golftipps!
Paul Picard

7

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

1 Byte dank @ l4m2 eingespart

Für unsortierte Arrays behoben, da geklärt wurde, dass solche Eingaben zu erwarten sind.

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
Ich wollte gerade die Bearbeitung vorschlagen, die Sie gerade vorgenommen haben :)
ETHproductions

a=>(a.reverse()+'').replace(/(.),\1/g,(c,i)=>i*2).split`,`.reverse()?
14 m²,

@ l4m2 Das funktioniert bei einstelligen Eingaben, würde aber fehlschlagen [1024, 1024, 512, 512, 256, 256](ich glaube, dieser Testfall wurde später hinzugefügt).
Arnauld

@ Arnauld Nun, deine auch scheitern ...
14m2

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

6

05AB1E , 26 Bytes

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

Probieren Sie es online!

Verallgemeinerte Schritte

  1. Reduziere durch Subtraktion, um herauszufinden, wo sich aufeinanderfolgende Elemente unterscheiden
  2. Reduzieren Sie durch Subtraktion über die Indizes dieser Stellen, um die Länge aufeinanderfolgender Elemente zu ermitteln
  3. Teilen Sie die Eingabe in Abschnitte dieser Länge auf
  4. Teile Stücke in Paare auf
  5. Summiere jedes Paar
  6. Kehre jeden summierten Teil um
  7. Auf eindimensionale Liste reduzieren

5

Mathematica, 53 Bytes

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

Erläuterung

Split@#

Teilen Sie die Eingabe in Unterlisten auf, die aus Läufen identischer Elemente bestehen. dh {2, 2, 2, 4, 8, 8}wird {{2, 2, 2}, {4}, {8, 8}}.

#~Partition~UpTo@2

Partitionieren Sie jede der Unterlisten in Partitionslängen von höchstens 2. Dh {{2, 2, 2}, {4}, {8, 8}}wird {{{2, 2}, {2}}, {{4}}, {{8, 8}}}.

Plus@@@

Summe jeder Partition. dh {{{2, 2}, {2}}, {{4}}, {{8, 8}}}wird {{4, 2}, {4}, {16}}.

Reverse

Kehren Sie die Ergebnisse um, da der PartitionBefehl von Mathematica von links nach rechts geht, die Partitionen jedoch in eine andere Richtung weisen sollen. dh {{4, 2}, {4}, {16}}wird {{2, 4}, {4}, {16}}.

Join@@

Reduzieren Sie das Ergebnis. dh {{2, 4}, {4}, {16}}wird {2, 4, 4, 16}.


Hallo JHM! Danke für die Antwort. Ich verstehe Mathematica nicht sehr gut. Könnten Sie ein wenig erklären, was hier vor sich geht?
Isaacg

Plus@@@ist Tr/@und ich denke, Sie können die Klammern vermeiden und Join@@wenn Sie ##&@@auf das Ergebnis von verwenden Reverse(habe es aber nicht getestet).
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;}

Die Eingabe ist eine ArrayList, die nur rückwärts durchläuft und bei Bedarf entfernt und verdoppelt.

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

Sie vergleichen LongReferenzen in Zeile 3 mit ==. Überlegen Sie a.get(i)-a.get(i-1)==0.
Jakob

4

Perl, 37 Bytes

Beinhaltet +4 für -0n

Mit der Eingabe als separate Zeile auf STDIN ausführen:

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

benötigt PHP 7.0; Nimmt Werte aus Befehlszeilenargumenten.

Laufen Sie mit -nroder versuchen Sie es online .


2
[2, 2, 2] gibt [4,2] anstelle von [2,4] zurück
Crypto

for($r=[];$v=($p=array_pop)($a=&$_GET[a]);)array_unshift($r,end($a)-$v?$v:2*$p($a));print_r($r);ist 1 Byte kürzer
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)

Die aufzurufende Funktion ist H

z.B H([1,2,2,4,8,2,])

Dies ist keineswegs der kürzeste Weg, dies in Julia zu tun. Aber es ist so cool, dass ich es trotzdem teilen wollte.

  • t(a) ist ein Werttyp, der den Wert (a) darstellt.
  • s(a) ist eine Instanz dieses Werttyps
  • gist eine Funktion, die die Differenzwerte (unter Verwendung der Wertetypen) und die Nummern ihrer Parameter berechnet. Und das ist cool
  • Kwickelt sich einfach gso ein

Extra cooles Teil:

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

Dies definiert den ^Operator, der auf Funktionen angewendet werden soll. Also das K^s(2)(X)ist das gleiche wie K(K(X)) so Hist gerade Aufruf KaufK ein paar Mal - oft genug sicherlich jeden verschachtelten Falles zum Einsturz

Dies kann viel, viel kürzer gemacht werden, aber dieser Weg ist einfach so lustig.


3

PowerShell v2 +, 81 Byte

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

Nimmt die Eingabe als explizites Array $n, kehrt sie um $n[$n.count..0], setzt -joindie Elemente zusammen mit einem Komma und fügt dann ein -replaceübereinstimmendes Ziffernpaar in das erste Element ein *2, a und ist in Parens eingeschlossen. Pipes, die sich ergeben (was für die Eingabe @(2,2,4,4)so aussieht (4*2),(2*2)), wechseln zu iex(kurz für Invoke-Expressionund ähnlich wie eval), wodurch die Multiplikation in tatsächliche Zahlen umgewandelt wird. Speichert das resultierende Array in $b, kapselt es in Parens, um es in der Pipeline zu platzieren, und kehrt es dann $bmit um [$b.count..0]. Lässt die resultierenden Elemente in der Pipeline und die Ausgabe ist implizit.


Testfälle

NB: In PowerShell ist das Konzept, ein leeres Array "zurückzugeben", bedeutungslos - es wird konvertiert,$nullsobald es den Gültigkeitsbereich verlässt - und entspricht daher der Rückgabe von nichts, wie hier im ersten Beispiel beschrieben (Nach einigen boshaften Fehlern). Darüber hinaus ist die Ausgabe hier durch Leerzeichen getrennt, da dies das Standardtrennzeichen für Zeichenfolgen-Arrays ist.

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}

16 Bytes dank @MayorMonty-Tipps auf dieser Seite
gespeichert

Das geht nicht. Testen mit [2,2,4,4]Erträgen [2,2,4,4].
Conor O'Brien

1
Jep. Knoten v6.2.1
Conor O'Brien

Meine schlechte .. Ich habe es mit einem anderen JS-Code in der gleichen Datei ausgeführt und die globalen Variablen wurden verwechselt.
Alexis_A

3

Brain-Flak , 60 Bytes

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

Probieren Sie es online!

Erläuterung:

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

Verwenden Sie die rechte Falte, um die Liste von hinten nach vorne zu erstellen (Sie können auch die linke Falte verwenden und die Liste am Anfang und Ende umkehren).

Wenn der Kopf der aktuellen Liste nicht mit dem nächsten Element übereinstimmt, das vorangestellt werden soll, stellen Sie ihn einfach voran.

Ansonsten entferne den Kopf der Liste (klingt grausam) und stelle das Element mal 2 voran.

Beispiel

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

2

Schläger 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))]  
        ))))

Testen:

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

Ausgabe:

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

Japt , 12 Bytes

ò¦ ®ò2n)mxÃc

Probieren Sie es online!

Ausgepackt und wie es funktioniert

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

Ich habe eine Idee von Jonathan Allans Jelly-Lösung .


0

Mathematica, 51 Bytes

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

{Longest@a___,x_/;x>0,x_,b___}Stimmt mit einer Liste überein, die zwei aufeinanderfolgende identische positive Zahlen enthält, und transformiert diese beiden Zahlen in -2x. Longestzwingt die Streichhölzer so spät wie möglich zu spielen.

Der Prozess wird Schritt für Schritt veranschaulicht:

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

Ein Makro, das regex rückwärts nach übereinstimmenden fortlaufenden Nummern sucht und diese zusammenfügt.

Das Eingabearray muss eine Zahl pro Zeile sein. Dieses Format erspart mir Striche, was nett ist, aber der wahre Grund ist, überlappende Regex-Übereinstimmungen zu umgehen. In Anbetracht der Zeichenfolge 222, wenn Sie /22nur das erste Paar passen werde, nicht das überlappende zweite Paar. Die Überlappungsregeln sind unterschiedlich, wenn die beiden Paare in unterschiedlichen Zeilen beginnen. In dieser Herausforderung [2, 2, 2]wird [2, 4], so das überlappende Paar passend ist kritisch.

HINWEIS: Die Challenge verlangte nur einen einzigen Durchgang. Aus diesem Grund müssen Sie haben :set nowrapscan. Mit :set wrapscankönnte ich eine Version erstellen, die den Job in mehreren Durchgängen abschließt, obwohl diese Lösung dies nicht immer tut.

  • <C-@>: Wenn Sie in einer Befehlszeile ein Literal eingeben, <CR>ohne den Befehl auszuführen, müssen Sie es normalerweise mit einem Escapezeichen versehen <C-V>. Aber du kannst tippen<C-@> unescaped und es wird als behandelt werden <C-J>/ <NL>, der wie sein wird , <CR>wenn Sie das Makro ausführen , aber nicht , wenn Sie eingeben. Versuchen Sie es mit Lesen :help NL-used-for-Nul.
  • @=: Diesmal kann ich ein aufgezeichnetes Makro nicht einfach verwenden, da der Eingang möglicherweise keine übereinstimmenden Paare enthält. Wenn dies passiert, während ein Makro ausgeführt wird, schlägt die erfolglose Suche fehl. Geschieht dies jedoch während des (impliziten ersten) Aufzeichnungsdurchlaufs, werden die restlichen Befehle im normalen Modus ausgeführt, wodurch die Datei beschädigt wird. Der Nachteil von@= ist, dass ich beim rekursiven Aufruf ein Byte verliere. manchmal kann man das @@als rekursiven aufruf benutzen , aber das würde laufen@" in diesem Fall von 4 Bytes früher ausgeführt.
  • DJ@"<C-A>-: DJlöscht die Zeile und fügt die Nummer (kein Zeilenumbruch) in ein Register ein, damit ich sie als Makro für ein Zahlenargument ausführen kann <C-A>. Ich muss -danach, damit ich in solchen Fällen kein zweites Match bekomme [4, 2, 2].

0

Perl6, 92 Bytes

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.