Hintergrund
Jellys arithmetische Atome werden automatisch vektorisiert. Tatsächlich ist x + y immer dann gut definiert, wenn x und y Zahlen oder zerlumpte Anordnungen von Zahlen sind. Jellys Quellcode implementiert dieses Verhalten mithilfe eines generischen Vektorisierers. Bei dieser Herausforderung werden jedoch nur Ganzzahlen und verschachtelte Ganzzahl-Arrays hinzugefügt.
Definitionen
Definieren Sie die Tiefe von x als 0, wenn x eine Ganzzahl ist, als 1, wenn es sich um ein (möglicherweise leeres) flaches Array von Ganzzahlen handelt, und als n + 1, wenn es mindestens ein Element der Tiefe n und keine Elemente der Tiefe k> enthält n .
Auf diese Weise hat 1 die Tiefe 0 , [] und [1] und [1, 1] die Tiefe 1 , [[], [] und [[1], [1] und [1] und [1] , []] haben die Tiefe 2 , [1, [1, [1]] haben die Tiefe 3 usw.
Die Operation x + y ist wie folgt definiert.
Wenn x und y die Tiefe 0 haben , geben Sie ihre Summe zurück.
Wenn x und y gleiche, aber positive Tiefen haben, wenden Sie rekursiv + auf alle Elemente von x und die entsprechenden Elemente von y an .
Wenn x und y unterschiedlich lang sind, hängen Sie das Ende des längeren Arrays an das Array der Summen an.
Gib das Ergebnis zurück.
Wenn die Tiefe von x streng kleiner als die Tiefe von y ist , wenden Sie rekursiv + auf x und alle Elemente von y an und geben Sie das Ergebnis zurück.
Machen Sie das Gegenteil, wenn die Tiefe von y strikt kleiner als die von x ist .
Betrachten Sie zum Beispiel die Operation [1, [2, 3], [4]] + [[[10, 20], [30], 40, 50], 60] .
Die Tiefe des linken Arguments ist 2 , während die Tiefe des rechten Arguments 3 ist. Wir berechnen also [1, [2, 3], [4]] + [[10, 20], [30], 40, 50 ] und [1, [2, 3], [4]] + 60 .
[1, [2, 3], [4]] und [[10, 20], [30], 40, 50] haben beide die Tiefe 2 , also berechnen wir 1 + [10, 20] , [2, 3] + [30] und [4] + 40 .
1 + [10, 20] = [1 + 10, 1 + 20] = [11, 21]
[2, 3] + [30] = [2 + 30, 3] = [32, 3]
Beachten Sie, dass 3 unberührt bleibt, da es kein passendes Element enthält.
[4] + 40 = [4 + 40] = [44]
50 kein passendes Element hat, so ist das Ergebnis [[[11, 21], [32, 3], [44], 50]] .[1, [2, 3], [4] + 60 = [1 + 60, [2, 3] + 60, [4] + 60] = [61, [2 + 60, 3 + 60], [ 4 + 60]] , was zu [61, [62, 63], [64]] führt .
Das Endergebnis ist [[[11, 21], [32, 3], [44], [50], [61, [62, 63], [64]] .
Aufgabe
Schreiben Sie ein Programm oder eine Funktion, die zwei Ganzzahlen, zwei verschachtelte Arrays von Ganzzahlen oder eine Kombination davon als Eingabe verwendet und deren Summe wie oben definiert zurückgibt.
Wenn Ihre Sprache über mehrere Array-ähnliche Typen verfügt (Listen, Tupel, Vektoren usw.), können Sie einen beliebigen Typ für Ihre Antwort auswählen. Der Rückgabetyp muss mit dem Argumenttyp übereinstimmen.
Um langweilige und unschlagbare Lösungen zu vermeiden , können Sie diese Sprache möglicherweise nicht verwenden , wenn eine Sprache genau diese Funktion aufweist.
Alle eingebauten Sprachen aller anderen Sprachen sind erlaubt. Wenn Ihre Sprache dies zulässt, können Sie den eingebauten Zusatz überladen und / oder neu definieren.
Das ist Code-Golf , also gewinnt der kürzeste Code in Bytes.
Testfälle
0 + 0 = 0
[-1, 0, -1] + [1] = [0, 0, -1]
[] + [0] = [0]
[] + 0 = []
[] + [] = []
[[], 0] + [] = [[], []]
[1, 2, 3] + 10 = [11, 12, 13]
[1, 2, 3] + [10] = [11, 2, 3]
[1, 2, 3] + [10, [20]] = [[11, 12, 13], [21, 2, 3]]
[1, 2, 3, []] + [10, [20]] = [11, [22], 3, []]
[1, [2, [3, [4]]]] + [10, [20]] = [[11, [21]], [[12, [22]], [13, [24]]]]
Um weitere Testfälle zu generieren, können Sie dieses Jelly-Programm verwenden .
Antworten:
Pyth, 42 Bytes
Testsuite
Die letzten 4 Bytes führen einfach die Funktion am Eingang aus.
quelle
APL, 44 Bytes
APLs
+
verteilen sich ebenfalls über Arrays, jedoch auf eine Weise, die nicht wirklich verwendet werden kann. Es gibt jedoch eine integrierte Tiefenfunktion (≡
).Erläuterung:
1=≡⍺⍵:⍺+⍵
: Wenn die Tiefen von⍺
⍵
beide Null sind (und daher die Tiefe von⍺ ⍵
1 ist), addieren Sie sie.∆←|≡¨⍺⍵
Nehmen Sie die absolute der Tiefe der beiden:⍺
und⍵
und speichern sie in∆
. (≡
Gibt einen negativen Wert zurück, wenn nicht alle Elemente die gleiche Tiefe haben.)=/∆
: wenn sie die gleiche Tiefe haben:↓↑⍺⍵
: Fülle das kürzeste Array mit Nullen auf, um es dem längeren Array anzupassen⊃∇¨/
: verteile die Funktion auf beide Arrays</∆
: Wenn die Tiefe von⍺
geringer ist als die von⍵
:⍺∘∇¨⍵
: binden⍺
und dann übermappen⍵
⍵∇⍺
: Wenn nichts anderes (also⍵
tiefer als⍺
) ist, tauschen Sie die Argumente aus und versuchen Sie es erneut.quelle
Mathematica, 122 Bytes
Definiert eine rekursive Funktion
f
, die die Summe berechnet. Diese Funktion nutzt die Mustererkennung von Mathematica und besteht aus vier separaten Definitionen:Wenn die Tiefe von
x
größer als die von isty
, tauschen Sie die Argumente aus, damit wir die Verteilung nur in eine Richtung handhaben müssen (was wir tun können, da die Addition kommutativ ist).Wenn die Tiefe von
x
weniger thann dass dery
Ersetzen jedes Wert#
iny
mitf[x,#]
, die Argumente von ungleichen Tiefen Pflege der Verteilung erfolgt.Wenn andernfalls ein Argument eine Liste ist (was impliziert, dass das andere auch eine Liste ist, da wir wissen, dass sie die gleiche Tiefe haben), fügen wir beide Argumente in eine Liste ein und füllen sie mit der gleichen Länge auf
PadRight[..., Automatic]
(was einfach a ausfüllt) zackiges Array mit Nullen, um es rechteckig zu machen), undMapThread
wenden Sie es dannf
auf die entsprechenden Paare aus den beiden Listen an.Und zum Schluss der Basisfall:
Wenn keines der anderen Muster übereinstimmt, müssen wir versuchen, zwei Zahlen hinzuzufügen, also machen wir das einfach.
quelle
Haskell, 150 Bytes
Erläuterung
Die erste Zeile definiert einen algebraischen Datentyp
L
, der entweder einS
Kalender (mit einemInt
) oder einV
Ektor (mit einer Liste vonL
s) ist, auf den mit einem Datensatz-Getter zugegriffen wird. Diesv
ist eine TeilfunktionL → [L]
.)Die zweite Linie definiert die Tiefe - Funktion: die Tiefe einer
V
ector ist eins plus seine maximale Tiefe. Ich stelleS 0
den Werten im Vektor voran , damitdepth [] == 1 + maximum [depth (S 0)] == 1
. Die Tiefe von "irgendetwas anderem" (einem Skalar) ist0
.Die dritte Zeile definiert den Basisfall für
!
(die Additionsfunktion): Die Summe der Skalare ist einfach ein Skalar.Die fünfte Zeile definiert eine Variante, bei der
zipWith (!)
nur Elemente aus der längsten Liste ausgewählt werden, wenn eines davon leer ist.Die vierte Zeile ist in drei Fälle aufgeteilt:
Wenn die Tiefe von
x
genau kleiner als die Tiefe von isty
, ordnen(x!)
Sie die Elemente von zuy
. (Die Verwendung vonv
ist garantiert gültig, dad(y) ≥ 1
.)Wenn die Tiefe von
x
strikt größer ist, drehen Sie die Argumente um und starten Sie neu.Wenn ihre Tiefen gleich sind, zippen Sie die Argumente zusammen mit
(!)
. (Die Verwendung vonv
ist garantiert gültig, da der Falld(x) = d(y) = 0
als Basisfall behandelt wurde.)Testfälle
Dann
show (lArg ! rArg) == "[[11,[21]],[[12,[22]],[13,[24]]]]"
.quelle
import
liegt daran, dass Ideone einen alten Haskell-Compiler hat. Moderne Versionen von GHC<$>
wurden eingeführtPrelude
, sodass SieControl.Applicative
heutzutage keinen Import mehr benötigen, um es zu verwenden.Java,
802794754746 BytesIch habe mich für @ Dennis ♦ entschieden, um die Herausforderung zu bewältigen, Strings "als letzten Ausweg" zu bearbeiten, weil es wahrscheinlich "zu kompliziert" war. Auch in der schlechtesten Sprache zum Golfen.
Arrays in der Eingabe sind durch Kommas getrennt, in eckigen Klammern und ohne Leerzeichen.
Volles Programm mit Funktionen, die in eine Klasse eingebunden sind, und mit Testfällen
Ich könnte dies später nach C ++ portieren, da es sich um die andere Sprache handelt, die keine zerlumpten Arrays unterstützt, da ich mir
ziemlich sicherbin,dasssie kürzer als diese Antwort sein wird. Dies war größtenteils ein Proof of Concept, aber Golftipps sind immer noch willkommen!-31 Bytes von @ user902383, die die Verwendung von foreach über ein konvertiertes Zeichenarray vorschlagen, und dann habe ich ein wenig mehr davon gespart, die if-Blöcke im letzten Teil neu anzuordnen.
quelle
Object[]
, die entweder verschachtelteObject[]
oder enthältInteger
. Oder einfach eine nicht generische Liste.Python 2.7,
261209202198191185197181 BytesFGITW triviale Lösung
EDIT: Natürlich schlägt @Dennis es
Vielen Dank an @LeakyNun für das Speichern von 57 Bytes mit Tipps zu Lambda-Ausdrücken und 2 Bytes aus nicht benötigten Klammern.
Vielen Dank an @Adnan für 4 Bytes aufgrund des Vorschlags,
type
anstelle von zu verwendenisinstance
Danke an @Lynn für 7 Bytes mit
-~
undmap
Vielen Dank an @FryAmTheEggman für
z>=[]
statttype
+12 Bytes, um Lambda in if else umzuwandeln und einen größeren Fehler zu beheben
-16 Bytes dank @Kevin Lau - nicht Kenny
Probieren Sie es online aus
quelle
z==[]or`z`>']'and ...
max(d(a)+1for a in z)
mit-~max(d(a)for a in z)
ein Byte spart (weil Sie den Raum vorher entfernen könnenmax
). Welches ist dann gerade-~max(map(d,z))
.[p(a,b)for a,b in zip(x,y)]
inmap(p,x,y)
. Sie können dies immer noch in 3 tun, aber Sie müssen einen Anruf hinzufügenlist
. Ich denke, Sie könnten auch Lynns Vorschlag verbessernz>=[]
. Unabhängig davon sollten Sie auch dietype
Vergleichsreihenfolge austauschen können, um Platz zu sparen.or`z`>'['
natürlich, aber ich kann meinen Kommentar nicht mehr ändern. Ist aber in der Tatz>[]
noch kürzer (der==
Fall ist schon erledigt)!Python 2,
145136 BytesTeste es auf Ideone .
Wie es funktioniert
In Python 2 sind alle Ganzzahlen kleiner als alle Wörterbücher, aber alle Listen sind größer. d berechnet rekursiv die Tiefe von t, indem es 0 für ganze Zahlen oder das inkrementierte Maximum der Tiefen seiner Elemente und 0 zurückgibt .
t+[0]
Vermeidet die Sonderanfertigung der leeren Liste.s berechnet rekursiv die Jelly-Summe von x und y .
Wenn die Tiefe von y die von x überschreitet ,
s(y,x)
ruft s mit vertauschten Argumenten auf und stellt dabei sicher, dass d (x) ≤ d (y) ist .Wenn y eine positive Tiefe hat,
map(s,(x,[x]*len(y))[d(x)<d(y)],y)
gilt Folgendes.Wenn die Tiefen von x und y übereinstimmen,
map(s,x,y)
wird s über alle Elemente von x und die entsprechenden Elemente von y abgebildet .Im Fall von Listen unterschiedlicher Länge, Karte wird passiert Keine als linkes oder rechtes Argument für Elemente in der kürzeren Liste fehlt.
Wenn die Tiefe von x geringer als die von y ist , wird es ausgeführt
map(s,[x]*len(y),y)
, indem s (x, ·) über y abgebildet wird .Wenn y (und daher x ) die Tiefe 0 hat , werden
(x or 0)+(y or 0)
falsche Argumente ( Keine oder 0 ) durch Nullen ersetzt und die Summe der resultierenden ganzen Zahlen zurückgegeben.quelle
JavaScript (ES6), 152 Byte
quelle
Ruby 2.3,
143145148149 BytesRuby hat all diese kleinen Macken darin, wie es
zip
mit Arrays unterschiedlicher Länge undmap
mit Funktionen mit mehreren Argumenten funktioniert, was das Golfspielen zum Vergnügen macht.quelle
map
mit einer Zwei-Argument-Funktion ausgeführt werden, wie ich sie am Ende eingerichtet habe. Hier ist eine für 2.1 bearbeitete Version, die funktioniert und denmap
Aufruf am Ende optimiert .ideone.com/q1jqTAJulia, 113 Bytes
Probieren Sie es online!
Wie es funktioniert
Erstellt einen 1-Byte-Alias für endof , der die Länge eines Arrays zurückgibt.
definiert eine Tiefenfunktion. Die Tiefe von t ist genau dann Null, wenn 0t == 0 ist . Wenn nicht, t ein Array und seine Tiefe wird als inkrementiertes Maximum der Tiefen seiner Elemente und 0 berechnet .
[t;0]
Hängt eine 0 an das Array t an und vermeidet so die Notwendigkeit, das leere Array in Sonderfällen zu behandeln.Julias eingebaute Summe + verhält sich bereits wie Jellys Summe, wenn eines (oder beide) seiner Argumente eine Ganzzahl ist. Die Summe von zwei Arrays ( + ) erfordert jedoch Arrays derselben Form, und selbst die vektorisierte Summe ( . + ) Erfordert Arrays, die in einer gemeinsamen Form übertragen werden können.
Wir definieren + für ein Paar Arrays über neu
Dies hat keine Auswirkungen auf die Definition von + für Ganzzahl- / Ganzzahl-, Array- / Ganzzahl- oder Ganzzahl- / Array-Argumente.
(!x,~x)>(!y,~y)
vergleicht lexikographisch die Tiefen- und Längenpaare von x und y . Wenn die Tiefe von x die von y überschreitet oder wenn ihre Tiefe übereinstimmt und die Länge von x die von y überschreitet , wird +y+x
rekursiv mit vertauschten Argumenten aufgerufen.Andernfalls wird
!x<!y
geprüft, ob die Tiefe von x geringer als die von y ist . Wenn es so ist,map(t->x+t,y)
bildet x + · über y .Wenn die Tiefen übereinstimmen, wird
~x<~y
geprüft, ob x kürzer als y ist . Wenn dies der[x;0]+y
Fall ist, wird + rekursiv aufgerufen, nachdem eine 0 an das linke Argument angehängt wurde.Wenn schließlich Tiefe und Länge identisch sind,
x.+y
wird + auf alle Elemente von x und die entsprechenden Elemente von y abgebildet .quelle