Lassen Sie sich von einem einfachen Zahlensystem erzählen. (was ich nur für diese Herausforderung erfunden habe)
Dieses System enthält die Funktionen ()
, []
, {}
, und <>
.
1. ()
Wenn ()
keine Argumente angegeben werden, wird dies zu ausgewertet 0
.
Wenn ()
ein oder mehrere Argumente angegeben werden, ergibt dies die Summe der Argumente.
2. []
Wenn []
keine Argumente angegeben werden, wird dies zu ausgewertet -1
.
Wenn []
ein oder mehrere Argumente angegeben werden, ergibt dies das erste Argument abzüglich der Summe der anderen Argumente.
3. {}
Wenn {}
keine Argumente angegeben werden, wird dies zu ausgewertet 1
.
Wenn {}
ein oder mehrere Argumente angegeben werden, wird das Produkt dieser Argumente ausgewertet.
4. <>
Wenn <>
keine Argumente angegeben werden, wird dies zu ausgewertet 1
.
Wenn <>
ein oder mehrere Argumente angegeben werden, wird das erste Argument als Ganzzahl dividiert durch das Produkt der anderen Argumente ausgewertet.
Deine Aufgabe
Wenn ein String eine gültige Zahl enthält (dh Klammern sind ausgeglichen, keine Division durch 0 usw.), wird sein Wert in diesem einfachen Zahlensystem ausgegeben.
Testfälle
() -> 0
(()()) -> 0
([][]) -> -2
({}<>) -> 2
({}[]) -> 0
[] -> -1
[[][]] -> 0
[()<>] -> -1
{()} -> 0
{([]<>)} -> 0
Denken Sie daran, das ist Code-Golf , also gewinnt der Code mit den wenigsten Bytes.
quelle
5/3
,5/-3
,-5/3
und-5/-3
?Antworten:
Dyalog APL , 94 Bytes
o←{(⊂(1⊃⍵),⍺⍺⊃⍵),2↓⍵}⋄u←{(⊃⍵,⍺⍺1)⍺⍺⍵⍵/1↓⍵}⋄⍎⍕'+/o' '-u+o' '×/o' '÷u×o' '(⊂⍬),'[')]}>'⍳⌽⍞],'⊂⍬'
Verwendet
⎕IO←0
wird
)]}>
durch einen Funktionsaufruf ersetzt , der einen Stapel annimmt, eine Operation auf sein oberes Bild anwendet, es löscht und das Ergebnis an sein nächstes Bild anfügt (dafür wird der monadische Operatoro
verwendet; der dyadische Operatoru
behandelt die komplizierteren Fälle von-
und÷
)wird
([{<
durch Code ersetzt , der dem Stack einen Frame hinzufügt ((⊂⍬),
)führt den resultierenden Ausdruck (umgekehrt, um der Ausführungsreihenfolge von APL zu entsprechen) mit einem Anfangsstapel von einem leeren Frame aus (
⊂⍬
)quelle
Haskell,
357306277251228224188185180 BytesEin Token-basierter Parser mit einem expliziten Stack.
(%)
Nimmt einen Token-Stack und ein Zeichen und drückt entweder (Opcode, Standardnummer) oder (0, Nummer) für({[<
, oder gibt die obersten Zahlen und einen opcode ein und drückt die Antwort für)}]>
. Opcodes werden von einem ASCII-Aufzählungs-Hack codiert.Ein großes Lob an @ChristianSievers für seine großartige Leistung Antwort , von der ich einige Ideen ausgeliehen habe.
Einzeiler!
Jetzt mit weniger Fehlerbehandlung! Verwendung:
Vielen Dank an @ChristianSievers für das Speichern von 14 + 3 Bytes!
Vielen Dank an @Zgarb für das Speichern von einigen + 4 Bytes!
quelle
(0,[0,0,1,-1,1]!!o):s
in der fünften Zeile?!
, damit Sie(s:_)!_=d s
den zweiten Fall durchführen können. Auch ich denke, Sie könntenx<-p$d<$>init a,y<-d$last a
im letzten Fall von binden%
.%
können Sie Parens um_:b
und ablegeng c
.Python 2,
292265248235223206204 BytesErsetzt alle Klammern durch ein Lambda, das die gleiche Funktion wie die Klammer hat, und wertet dann den resultierenden Python-Code aus. Benötigt seine Eingabe in Anführungszeichen, wie
'[<><>([]{})]'
.Dieses Programm speichert den Klammertyp als erstes Zeichen in jeder Zeichenfolge im
for
und alles nach dem Schlüsselwortlambda
als Rest. Dann wird das erste Zeichen zum Ersetzen verwendet. Der Rest wird zu einem Lambda-ähnlichen Wert kombiniert(lambda*x:sum(x))()
.Probieren Sie es auf Ideone!
quelle
PEG.js (ES6) , 132 Bytes
Sollte jetzt behoben sein.
Erläuterung
Besser lesbar:
PEG.js ist eine erweiterte Version von Javascript, die speziell für das Parsen entwickelt wurde. Es ist sehr streng, weshalb ich verwenden musste
var
. Außerdem scheint es einen Fehler mit eckigen Klammern innerhalb von Strings zu geben, der den Code erheblich aufblähte.Zunächst definieren wir eine Regel
x
, die mit einer beliebigen Klammer übereinstimmta
, die mehrere Ausdrücke enthalten kann oder nicht, die mit der Regel übereinstimmenx
.Für jede zu regelnde Übereinstimmung geben
x
wir eine 0 in das Array der inneren Übereinstimmung ein,b
wennb
die Länge 1 ist.Wenn
b
die Länge> 0 ist, finden wir den Index vona
in([<
und erhalten ein Zeichen aus+-/
diesem Index. Wenn das Ergebnis undefiniert ist (das heißt dasa
war{
), machen wir das Ergebnis zu*
. Schließlich wenden wir uns einem Leerzeichen zu und schließen unsb
dem Ergebnis an.Wenn
b
die Länge = 0 ist, finden wir den Index vona
in([<
und erhalten ein Zeichen aus10
diesem Index. Wenn das Ergebnis undefiniert ist (dh dasa
war{
oder<
), machen wir das Ergebnis zu 2. Schließlich dekrementieren wir einfach.Am Ende können wir nur den Ausdruck bewerten und das Ergebnis begrenzen.
quelle
Perl, 113 + 2 = 115 Bytes
Laufen Sie mit
-lp
(2-Byte-Strafe).Besser lesbar (Hinweis: Diese "besser lesbare Version" wird nicht ausgeführt, da ich Kommentare an Stellen platziere, an denen sie syntaktisch nicht zulässig sind.):
Die Grundidee ist, dass wir eine Eingabe wie
[()<>]
in das Perl-Programmb(a(0),d(0),0),
per Textverarbeitung konvertieren . Perl ist mit dem nachgestellten Komma einverstanden. Früher haben wir die Funktionen definierta
,b
,c
,d
die gleiche Wirkung wie das haben()
,[]
,{}
,<>
sind die Umsetzung Konstrukte aus der Sprache , die wir; Sie ignorieren jeweils ihr letztes Argument (die 0 am Ende), das enthalten ist, um sicherzustellen, dass alle Eingaben korrekt analysiert werden, und verwenden die in der funktionalen Programmierung übliche Implementierung, bei der Kopf und Schwanz getrennt verarbeitet werden. Weilb(e,f,g,0)
meanse-f-g
, dh sein erstes Argument speziella
behandelt , währenda(e,f,g,0)
means seine Argumente symmetrisch behandelte+f+g
, implementieren wira
rekursiv undb
per Aufrufa
.c
undd
haben eine ähnliche Beziehung. Alle vier Funktionen sind sich sehr ähnlich, daher generieren wir sie zur Laufzeit, anstatt sie separat zu implementieren. Wir speichern eine Vorlage, die für alle vier Funktionen in einer Zeichenfolge gilt, und generieren dann die Funktionen, indem wir Zeichen in die Vorlage einsetzen.Da Perl eine
/
Gleitkommadivision durchführt, ist{}
dies auch bei der Implementierung der Fall. Ich gehe davon aus, dass dies entweder kein eigenständiges Problem ist oder dass die-Minteger
Auswahl einer Sprachvariante (bei der alle arithmetischen Operationen Ganzzahloperationen sind) kostenlos ist, da ich sonst zusätzliche Bytes für das Schreiben einer Ganzzahldivision in Perl aufwenden müsste. Das scheint nicht das zu sein, worum es im Grunde geht. (Ich glaube , man müßte vier Bytes verbringt Wechsel(shift)
zuint+(shift)
;. Ich kann das nicht getestet)quelle
Oktave,
215206198 Bytesversuche es online
quelle
PHP,
315300285258250244 BytesErsetzt Unterausdrücke durch Unterstrich + Wert. Die Schleife bricht ab, wenn die Iteration nicht ersetzt wurde.
19 Jahre, seit ich C das erste Mal getroffen habe, 17 Jahre Arbeit mit PHP;
Dies ist das erste Mal, dass
strtok
es Sinn macht, 24 Bytes einzusparen!Nervenzusammenbruch
quelle
ES6 (Javascript),
250,171,154,149147 BytesEine reine Javascript-Version.
"Metaprogramming" (wie die meisten anderen Antworten hier) konvertiert den eingegebenen Programmtext in ein entsprechendes Javascript-Programm, indem eine Reihe direkter Textsubstitutionen daran vorgenommen werden (dh die Programmstruktur bleibt unverändert).
Kann wahrscheinlich weiter golfen werden.
UPDATE (v2.1)
UPDATE (v2)
Nur erkannt, dass ausstehende Kommas in ES-Arrays vollständig gültig sind, sodass der gesamte Kommanormalisierungscode entfernt werden kann. Es folgte auch ein ausgezeichneter Rat von @Titus zur Optimierung der Alphabet-Suche.
UPDATE (v1)
Doppelter "Ersetzen" -Alias wurde entfernt.
UPDATE (v1)
Verwenden Sie ein besseres Alphabet: () => 1+ [] => 0 {} => 2 * <> => 2 / (jedes Zeichen kann direkt als Wert oder Operator wiederverwendet werden)
Redu () durch replace () ersetzt (Alphabetische Zuordnung)
Konstante Inlining-, Open- und Closing-Bracket-Verarbeitung in einem Schritt zusammengeführt
Golf (v2.1)
Golf (v1)
Golf (v0)
Erklärt (v0)
Prüfung
Ausgang testen
quelle
s.reduce((r,c)=>r+="abcdefgh"["()[]{}<>".indexOf(c)],'')
(-5) gehen? In diesem Fall können Sie sich anindexOf
eine Variable erinnern und den Operator aus einem dritten Zeichenfolgenliteral übernehmen.Haskell,
184 179 172 161 160 159 151 148145 BytesRekursiver Abstieg, Threading der Eingabe wegen Haskell. Wie üblich ist die letzte Zeile keine Definition, sondern gibt die Funktion an, die das Problem löst. Um dies zu testen, setzen Sie die Zeilen mit Ausnahme der letzten in eine Datei, laden Sie sie und führen Sie so etwas aus:
Vielen Dank an @Zgarb für die Inspiration und viele detaillierte Hinweise und an @Angs für die Inspiration von seiner Lösung und weiteren Hinweisen.
Es wurde nicht festgelegt, wie sich die Division bei negativen Ganzzahlen verhalten soll. Wie auch immer, die wiederholte Verwendung
div
scheint falsch, da sie nicht mit derdiv
einmaligen Verwendung des Produkts der verbleibenden Werte identisch ist . Wennquot
ich jetzt benutze , erhalte ich die gleichen Ergebnisse für<{}([][])[]>
und<{}{([][])[]}>
.Für schönen, fast lesbaren Code schauen Sie sich die erste Version an. Die Zwischenversionen enthalten alle Arten von nettem und einschüchterndem Code und helfen, diese Version zu verstehen.
quelle
(!)=(,)
indem Sie!
statt expliziter Tupel definieren und verwenden .m x
undd x
als1#x
und definieren0#x
, können Sie die Fällem[x]
undd[x]
in einen zusammenführen, was meiner Meinung nach auch einige Bytes einspart.!
Trick nicht auszahlt. Dein zweiter Vorschlag ist böse, da geht mein fast lesbarer Code ... Clever!s%(c:i)=(s?c,i)
unds?')'=sum s
usw. viel kürzer sein werden, da Sie die wiederholteni
s loswerden können . ..Keine Wartezeit, das wird wahrscheinlich wegen dess%(_:i)
Falls nicht funktionieren .elem
unddiv
, das sollte ein paar Bytes mehr sparen.JavaScript (ES6), nein
eval
, 156 ByteErläuterung: Der reguläre Ausdruck findet die erste nicht verarbeitete schließende Klammer und stimmt mit der (vermutlich) entsprechenden öffnenden Klammer und allen dazwischen liegenden Argumenten überein. Die Argumente werden entsprechend der Operation aufgeteilt und reduziert (leider sind '(' und '[' nicht das optimale Paar für
+
und-
), oder wenn es keine Argumente gibt, wird der entsprechende Wert berechnet (wiederum ist die Übereinstimmung von Zeichen mit Werten suboptimal) aus meiner Sicht) .Das Ergebnis wird dann durch ein vorangestelltes Leerzeichen ersetzt, um es von anderen Ergebnissen zu trennen.Die Funktion ruft sich dann rekursiv auf, bis keine Änderungen mehr vorgenommen werden müssen, und gibt in diesem Fall den resultierenden Wert zurück. Beispiel:quelle