Haskell hat Tupel, die als geschrieben werden können
(a,b,c)
Dies ist jedoch nur syntaktischer Zucker für
(,,)a b c
Im Allgemeinen kann ein n- Tupel mit n-1 ,
s zwischen (
... )
und den durch Leerzeichen getrennten Elementen gebildet werden. Beispielsweise kann das 7-Tupel (1,2,3,4,5,6,7)
durch gebildet werden
(,,,,,,)1 2 3 4 5 6 7
Da Haskell keine 1-Tupel hat, können sie nicht gebildet werden. Sie sind auch nicht für leere Tupel verantwortlich.
Verschachtelte Tupel können mithilfe von Parens gebildet werden, um die Reihenfolge der Operationen zu überschreiben.
((1,2),3) == (,)((,)1 2)3
Als Teil unseres Strebens, allen syntaktischen Zucker aus Haskell zu entfernen, werde ich Sie bitten, ein Programm zu schreiben, das syntaktischen Zucker auch aus Haskells Tupeln entfernt.
Ihr Programm sollte ein Tupel, ein Array oder eine Zeichenfolge, die ein zuckerhaltiges Tupel darstellt, verwenden und eine Zeichenfolge ausgeben, die ein "zuckerfreies" Tupel darstellt. Eingabetupel enthalten immer nur positive ganze Zahlen oder andere Tupel.
Da wir hier Golf spielen, sollte Ihre Leistung kurz sein. Es sollte nicht unnötig enthalten
Räume. Leerzeichen sollten nur verwendet werden, um Argumente von Tupelfunktionen zu trennen. Sie sollten nicht nach
)
oder vor a stehen(
Klammern. Klammern sollten nur beim Bilden von Tupelfunktionen oder beim Verschachteln von Tupeln verwendet werden.
Dies ist eine Code-Golf- Frage, daher werden die Antworten in Bytes bewertet, wobei weniger Bytes besser sind.
Testfälle
(1,2) -> (,)1 2
(1,2,3) -> (,,)1 2 3
((1,2),3) -> (,)((,)1 2)3
(1,2,3,4) -> (,,,)1 2 3 4
(1,(2,3)) -> (,)1((,)2 3)
(10,1) -> (,)10 1
,
((1,(2,3)),4,(5,6))
und(1,(2,3),4)
.Antworten:
Haskell ,
169.148BytesProbieren Sie es online! Nimmt das Tupel als String.
init.tail.fst.([]%)
ist die anonyme Hauptfunktion. Binden Sie es an zBf
und verwenden Sie gernef "(3,(14,1),4,7)"
, was ergibt"(,,,)3((,)14 1)4 7"
.Warum wird die Eingabe nicht als Haskell-Tupel bereitgestellt? Da Haskell stark typisiert ist, hat ein Tupel
(1,2)
den Typ(Int,Int)
1 und ein Tupel(1,(2,3))
den Typ(Int,(Int,Int))
. Somit kann eine Funktion, die die erste Art von Tupel akzeptiert, nicht auf die zweite Art angewendet werden, und insbesondere kann es keine Funktion geben, die ein beliebiges Tupel 2 akzeptiert .Erläuterung:
p:k="(,"
ist ein kurzer Weg zuweisenp
zu'('
undk
zu","
.(%)
ist die rekursive Analyse- und Konvertierungsfunktion. Das erste Argument ist eine Liste bereits geparster Tupeleinträge, das zweite Argument ist der Rest der ursprünglichen Zeichenfolge. Jeder Aufruf gibt ein Tupel des aktuell konvertierten Tupels (als Zeichenfolge und in Klammern) und den Rest der Zeichenfolge zurück.l%('(':r)
Wenn die Zeichenfolge mit einer öffnenden Klammer beginnt, müssen wir einen neuen Tupeleintrag analysieren.(y,x:s)<-[]%r
Wir wenden rekursiv an%
und erhalten einen Tupeleintragy
und die verbleibende Zeichenfolge wird in das nächste Zeichenx
und den Rest der Zeichenfolge aufgeteilts
.m<-y:l
Wir fügen den neuen Eintragy
der aktuellen Liste der bereits gefundenen Einträge hinzul
und rufen das Ergebnis aufm
.x
ist jetzt entweder ein Komma,
oder eine schließende Klammer)
. Daslast$ <B> :[ <A> |x<',']
ist nur eine kürzere Schreibweiseif x == ')' then <A> else <B>
.,
als nächstes kommt, müssen wir den nächsten Eintrag rekursiv analysieren:m%(p:s)
Wir stellen eine öffnende Klammer voran, um im richtigen Fall zu landen und die Liste der bereits gefundenen Einträge zu übergebenm
.x == ')'
haben wir das aktuelle Tupel beendet und müssen die erforderliche Transformation durchführen:(p:p:(l>>k)++x:foldl(\r x->x++[' '|x>k,r>k]++r)[x]m,s)
p:p:(l>>k)++x:
Wenn wir n Einträge gefunden haben,m
hat die Liste vor dem Hinzufügen des zuletzt gefundenen Elements n Elemente und n-1 Einträge. Dies ist praktisch, da wir n-1 für ein Elementtupel benötigen und Listen so bearbeiten, dass "die Liste mit sich selbst so oft verkettet wird, wie es Elemente gibt" . Somit ergibt dieser erste Teil einen String wie .y
,
n
l>>k
k
y
"((,,,)"
foldl(\r x->x++[' '|x>k,r>k]++r)[x]m
Verkettet die Elemente vonm
(in umgekehrter Reihenfolge, da durch Hinzufügen neuer Einträge an der Vorderseitem
selbst in umgekehrter Reihenfolge erstellt wurde), während nur Leerzeichen zwischen zwei Elementen hinzugefügt werden, wenn es sich um beide Zahlen handelt:[' '|x>k,r>k]
Wir überprüfen durch lexikografischen Vergleich , ob die aktuellen Einträgex
undr
Zahlen sind sie zu","
- wenn sie keine Zahlen sind, sind sie bereits eine Tupel-Darstellung in eckigen Klammern und'(' < ','
halten.l%('(':r)
gleich zu Beginn ausfällt, dann enden wir in der letzten Zeile nach oben:l%r=lex r!!0
. Das heißt, wir müssen eine Zahl analysieren und die Zahl und den Rest der Zeichenfolge zurückgeben. Zum Glück gibt es dielex
Funktion, die genau das macht (sie analysiert das nächste gültige Haskell-Token, nicht nur Zahlen). Das resultierende Tupel wird jedoch in eine Liste eingeschlossen, sodass wir!!0
das erste Element der Liste abrufen.init.tail.fst.([]%)
ist die Hauptfunktion, die eine Zeichenfolge akzeptiert und%
mit einer leeren Liste darauf angewendet wird. ZB für eine Eingabe"(1,2)"
, die([]%)
Ausbeuten anwendet("((,)1 2)","")
, müssen das äußere Tupel und die Klammern entfernt werden.fst
Ruft das erste Element des Tupels ab,tail
entfernt die schließende undinit
die öffnende Klammer .Edit: Vielen Dank an @ Ørjan Johansen für das Golfen von insgesamt 21 Bytes !
1 Eigentlich ist der Typ (Num t1, Num t) => (t, t1) , aber das ist eine andere Geschichte.
2 Ignorieren Sie polymorphe Funktionen wie id , die mit ihren Eingaben nicht funktionieren.
quelle
Desugarable
, aber man müsste Instanzen fürInt
und alle Tupeltypen deklarieren .g
kann gekürztfoldr1(\x r->x++[' '|x>k,r>k]++r)
und inliniert werden.show (1,2,3,4,5,6,7,8,9,0,1,2,3,4,5)
in GHCi, fügen Sie dann,6
am Ende eine hinzu und versuchen Sie es erneut.)m<-y:l
, falten Sie links statt rechts und verwenden Sie[x]
als Anfangswert. Probieren Sie es online!f
kann anonym bleiben:init.tail.fst.([]%)
.Haskell,
141 Bytes138 Bytes (Dank an Ørjan Johansen)f
hat TypExp -> String
.Eingabe: eine Template-Haskell-
Exp
Ression (dh die Standard-AST-Darstellung von Haskell-Werten beliebigen Typs - im Grunde analysiert Haskell-Code vor der Typüberprüfung); muss ein Tupel darstellen, das nur nichtnegative Ganzzahlen und andere solche Tupel enthält.Ausgabe: Eine Zeichenfolge, die die Syntax für den Tupelausdruck enthält.
Demo:
quelle
")"++
an')':
zwei Stellen zu wechseln und den Platz nach dem zu speichern,tail
indem Sie ihn außerhalb der Klammern verschieben.Haskell , 119 Bytes
Probieren Sie es online! Dies verwendet einen benutzerdefinierten Datentyp
T
, um Tupel darzustellen, dh ein Tupel((1,2),3)
wird als dargestelltU[U[I 1,I 2],I 3]
. Anwendungsbeispiel:init.tail.f $ U[U[I 1,I 2],I 3]
Erträge(,)((,)1 2)3
.quelle
Python 2 , 110 Bytes
Probieren Sie es online!
Nimmt ein
tuple
.quelle
GNU sed,
14982 + 2 = 84 Bytes+2 Bytes für
-r
Flag.Probieren Sie es online!
Erläuterung
quelle
((1,(2,3)),4,(5,6))
und(1,(2,3),4)
.JavaScript, 75 Byte
Eingabearray von Nummer | Array, Ausgabezeichenfolge.
Dank Neil sparen Sie 2 Bytes
quelle
(1/t?' ':0)+v
kann sein1/t?' '+v:v
.Mathematica, 94 Bytes
Enthält eine nicht druckbare
U+F4A1
, eingebauteFunction
Funktion.Nimmt eine
List
ganze ZahlString
s. Wenn dies nicht erlaubt ist, kann dies durch Hinzufügen von 10 weiteren Bytes behoben werden (diese Version benötigt eineList
vonList
s /Integer
s):quelle
Pip , 45 Bytes
Dies ist eine Funktion, die eine Liste als Argument verwendet. Probieren Sie es online!
Kommentierte Version
quelle
JavaScript (ES6),
8884 BytesNimmt ein Array von ganzen Zahlen und Arrays. Bearbeiten: 1 Byte durch Verwendung von
s+=
anstelle von zwei separaten Verwendungen von gespeicherts+
. Sparte jetzt weitere 3 Bytes, da ich das innere Ternär vereinfachen kann. Wenn ich @ tshs Ideen stehle, kann ich es auf 76 Bytes reduzieren:quelle
Your program should take either a tuple or a string representing a sugary tuple
Ich würde annehmen, dass ein Array von Arrays / ganzen Zahlen in Ordnung sein sollte.R 316 Bytes?
(Ich bin mir nicht sicher, wie ich die Bytes richtig zählen soll. Außerdem ist es keine großartige Lösung, aber ich wollte es veröffentlichen, da ich die Zeit damit verbracht habe, es zu machen.)
Testfälle:
quelle
JavaScript (ES6), 72 Byte
Eingabe: Array mit Zahlen und / oder Arrays
Ausgabe: String
Verwendung: f ([...])
Beendet alle Testfälle, Verbesserungen erwünscht
quelle
C, 308 oder 339 Bytes
308 oder 339 Byte, abhängig davon, ob die Übergabe eines Zeigers an das Ende der Eingabezeichenfolge zulässig ist oder nicht; Die letzte Zeile dient nur dazu, ein String-Literal direkt zu übergeben, ohne seine Länge berechnen zu müssen.
Erläuterung
Ein ziemlich einfacher Algorithmus. Es zählt die Anzahl der Kommas in der aktuellen Tiefe, gibt sie als Tupelkonstruktor aus und folgt dann rekursiv den Argumenten des Tupels (Leerzeichen zwischen Zahlen, geschachtelte Tupel in Klammern).
Testfälle und Anwendung
quelle