Wir haben alle diese Online "Mathe-Hax" gesehen, die so aussehen:
Think of a number, divide by 2, multiply by 0, add 8.
Und durch Zauberei endet jeder mit der Nummer 8!
Sprache
Definieren wir eine Programmiersprache, die die Syntax des obigen Textes "WordMath" verwendet. WordMath-Skripte folgen dieser Vorlage:
Think of a number, <commandlist>.
Was im Grunde bedeutet: Nimm eine Zahl (als Eingabe von STDIN) als anfänglichen Akkumulator, führe alle Befehle darauf aus und gib das Ergebnis aus.
Die Befehle werden durch das Trennzeichen ,
(Komma + Leerzeichen) getrennt. Die gültigen Befehle sind (Anmerkung, #
die eine nicht negative Ganzzahl darstellt :) :
add #
/subtract #
- Addiere / subtrahiere den Wert vom Akkumulator.divide by #
/multiply by #
- floordiv / multipliziere den Akku mit dem angegebenen Wert.subtract from #
- Ähnlich wiesubtract
, aberacc = # - acc
stattdessenacc = acc - #
repeat
- Wiederholen Sie den letzten Befehl. Dies kann nicht der erste Befehl sein, Sie müssen jedoch mehrere aufeinanderfolgende Wiederholungen unterstützen.
Die Herausforderung
Ihre Aufgabe ist es, ein Programm oder eine Funktion zu erstellen , die eine gültige WordMath Skript als Eingabe und transpiles es in ein gültiges volles Programm - in der Sprache des Code ist in.
Wenn sich mein Code beispielsweise in Python 2 befindet und das Skript wie folgt lautet:
Think of a number, subtract from 10, add 10, multiply by 2.
Das ausgegebene Programm kann sein:
a = input()
a = 10 - a
a += 10
a *= 2
print(a)
Oder alternativ:
print(((10-input())+10)*2)
Solange es sich um ein vollständiges Programm handelt, das Eingaben von STDIN
oder Ausdrucke an STDOUT
die nächsten Entsprechungen der Sprache vornimmt.
Regeln
- Ihr ursprüngliches Programm geht möglicherweise davon aus, dass die Eingabe immer ein gültiges WordMath-Skript ist.
- Die transpilierten Programme müssen nicht mit mathematischen Fehlern wie der Division durch 0 umgehen.
- Die transpilierten Programme können davon ausgehen, dass die Eingabe eine gültige Ganzzahl mit Vorzeichen innerhalb des Standard-Ganzzahlbereichs Ihrer Sprache darstellt.
- Das ist Code-Golf , also gewinnt die kürzeste Lösung (in Bytes).
- Nur die Anzahl der Bytes Ihres ursprünglichen Programms ist von Bedeutung - der ausgegebene Code kann so lang sein, wie Sie möchten!
Beispielskripte
Beispiel 1:
Think of a number.
Nehmen Sie Eingaben, tun Sie nichts, zeigen Sie sie an: WordMaths Katzenprogramm.
Beispiel 2:
Think of a number, divide by 5, subtract from 9.
Denken Sie daran, dass "Teilen" Bodenteilung ist, also für dieses Programm 6 -> 8
und 29 -> 4
.
Beispiel 3:
Think of a number, add 5, add 10, multiply by 2, subtract 15, repeat, divide by 2.
Das erweiterte Katzenprogramm!
Beispiel 4:
Think of a number, subtract 1, repeat, repeat.
Nimmt eine Zahl und subtrahiert 3.
-5/3
? Runden wir gegen0
oder gegen die negative Unendlichkeit?Antworten:
05AB1E ,
59565452 BytesProbieren Sie es online!
Mein Gehirn tut danach höllisch weh ... Es wird im 05AB1E-Code wie folgt ausgegeben:
Think of a Number
wird aufgrund impliziter Eingaben entfernt.Subtract From #
verdeckt zu#s-
(tauschena
undb
und führen Sie die Operation).Subtract #
konvertiert zu#-
.Add #
konvertiert zu#+
.Multiply by #
konvertiert zu#*
.Divide by #
konvertiert zu#/
.Repeat
greift nach dem zuletzt im Register gespeicherten und verkettet es.Erklärt:
Beispiel:
Eingang:
Ausgabe:
Probiere Lösung mit Eingabe von 10:
Probieren Sie es online!
Sehen Sie es auf Google:
Hier ist ein Link zu derselben Gleichung, die in Google eingegeben wurde.
quelle
C Präprozessor, 362 Bytes
Ich habe das fast nur im C-Präprozessor zum Laufen gebracht, aber der Wiederholungsbefehl erweist sich als viel zu schwierig zu implementieren. Stattdessen habe ich den Präprozessor verwendet, um die Eingabe in ein Array umzuwandeln, das dann von zusätzlichem Code interpretiert wird.
Die Eingabe muss in "input.wm" bereitgestellt oder einfach in der Quelle in dieser Zeile gespeichert werden. Ich habe seine Bytes in meine Zählung aufgenommen, weil ich finde, dass es ein bisschen hackig ist und leicht gegen die Regeln der Herausforderung verstößt, daher ist es nur passend.
Sobald Sie Ihre WordMath-Quelle in input.wm abgelegt haben, wo ein Compiler sie finden kann, sollten Sie dies mit Warnungen kompilieren können, um eine ausführbare Datei zu erstellen, die das tut, was die WordMath-Quelle sagt.
quelle
Netzhaut, 170 Bytes
Denn wer möchte das nicht sehen ?!
Ich dachte daran, wie großartig es wäre, eine Retina-Lösung zu sehen, und beschloss, sie schnell zu erstellen. Es dauerte nur eine Stunde. Die Anzahl der Bytes setzt wie üblich die Kodierung nach ISO 8859-1 voraus.
Probieren Sie es online aus
Die Ausgabe enthält eine nachgestellte Newline, die beim Testen des resultierenden Programms nicht kopiert werden sollte. Das Programm unterstützt keine Negative, weil Retina ganzzahliger Standardbereich (in Unary) dies nicht unterstützt.
Erläuterung:
Mathe-Programme:
Hinzufügen:
Fügen Sie die Anzahl der Einsen zum Anfang hinzu. 5 hinzufügen:
Subtrahieren:
Entfernen Sie die Anzahl von Einsen vom Anfang. Subtrahiere 5:
Subtrahieren von:
Ersetzen Sie die Eingabe
1
s durchx
s. Neben die feste Zahl setzen. Mehrmals entfernenx1
. Subtrahieren von 10:Mal:
Ersetzen Sie jeden
1
durch eine bestimmte Anzahl von ihnen. Mit 3 multiplizieren:Teilen durch:
Dies verwendet mein Retina-Programm für die Ganzzahldivision . Teilen Sie durch 2:
quelle
$
passt ganz am Ende der Zeichenfolge oder vor einem nachgestellten Zeilenumbruch. Sie brauchen,\z
wenn Sie nur die ersteren wollen.GNU awk, 139 Bytes
Aufruf:
Testfälle:
quelle
Haskell,
232231 BytesNatürlich würde ein funktionaler Programmierer es vorziehen, eine Funktion anstelle eines Strings zurückzugeben, der ein Programm darstellt, aber hier ist es:
Anmerkungen: Wir beginnen immer mit dem Hinzufügen von Null, da sonst die Transpilation des trivialen WordMath-Programms nicht genügend Informationen liefert, um auf den verwendeten Typ schließen zu
read
können.subtract from n
könnte als implementiert werden(n-)
, aber ich benutze((-)n)
für mehr einheitlichkeit. Wennsubtract n
ich dassubtract
von der Eingabe kopiere , muss ich es nicht schreiben, sondern muss den fehlenden Platz am Ende ausgleichen.repeat
wird als Standardoperation verwendet; zusammen mit einer leeren anfänglichen vorherigen Operation ermöglicht dies das einfache Ignorieren der ersten vier Wörter.Anwendungsbeispiel:
Die anderen Beispiele ergeben die folgenden Ergebnisse:
quelle
h
Vielleicht sieht so etwas aush s n r|x<-s.read.init$n=x%r.x
und wird mit dem ersten Argument eine Funktion genannt wieh(+)n r
(und es mussflip
irgendwo welche geben, um die richtige Operatorreihenfolge zu erhalten), Basisfall ist_%_=id
. Hauptfunktion kann das ganze Boilerplate vermeiden und gerade seint l=id%words l
. - Dank des Lehrens kann es als Dolmetscher gesehen werden, und diese Idee kann zu einer einfacheren und / oder kürzeren Lösung führen.Python 2,
263258260221 BytesDies könnte wahrscheinlich noch viel kürzer sein.
Probieren Sie es online aus
Ich benutze
//
stattdessen/
, weil die letzte Anweisung ein.
am Ende hat und jede Zahl zu einem float macht. Um die Division konsistent zu halten, verwende ich die Ganzzahldivision.Testfallausgabe:
quelle
if
so
wie folgt ändern (was meiner Meinung nach funktionieren sollte):o=[[o+[['+-'['s'in c],'//']['v'in c],'*']['m'in c]+n,n+'-'+o]['f'in c],'input()']['T'in c]
Sie können es auf 224 bringen.Befunge,
342305 BytesProbieren Sie es online!
Ausgabe
Der erzeugte Code beginnt mit einem
&
Befehl (Eingabewert) und endet mit Befehlen.
(Ausgabewert) und@
(Beenden). Dazwischen haben wir die verschiedenen Berechnungen in der Form<number><operation>
, wo die Operation stattfindet sein kann+
(add),-
(subtrahieren),/
(divide by),*
(multiplizieren) und\-
(subtrahieren).Die Zahl selbst ist etwas kompliziert, da Befunge nur numerische Literale im Bereich von 0 bis 9 unterstützt, sodass alles, was größer ist, manuell berechnet werden muss. Da wir die Zahlen bereits zeichenweise lesen, bauen wir die Zahl einfach auf, während jede Ziffer gelesen wird, sodass beispielsweise 123 wird
155+*2+55+*3+
, d(((1 * 10) + 2) * 10) + 3
. H.Beispiele
Erläuterung
Befunge ist nicht in der Lage, Zeichenfolgen als solche zu manipulieren. Daher wird der größte Teil des Parsings durch das Zählen von Zeichen erledigt. Wir beginnen einfach mit dem Überspringen der ersten 18 Zeichen, wodurch wir den Gedanken an eine Zahlenphrase (plus Komma oder Punkt) hinter uns lassen . Wenn das nächste Zeichen eine Form von Newline oder EOF ist, gehen wir direkt zur Ausgaberoutine, ansonsten suchen wir weiter nach einer Befehlsliste.
Um einen Befehl zu analysieren, zählen wir nur die Zeichen, bis wir eine Ziffer oder ein Trennzeichen erreichen. Wenn es sich um ein Trennzeichen handelt, muss es sich um den Wiederholungsbefehl handeln, den wir als Sonderfall behandeln. Wenn es sich um eine Ziffer handelt, fügen wir sie unserem Ausgabepuffer hinzu und suchen weiter nach weiteren Ziffern. Jedes Mal, wenn eine Ziffer ausgegeben wird, wird ihr ein Präfix vorangestellt
55+*
(um die bisherige Summe mit 10 zu multiplizieren) und mit einem Suffix versehen+
(um sie zur Summe hinzuzufügen) versehen. Sobald die Ziffern fertig sind, fügen wir das Befehlszeichen hinzu.Was die Bestimmung des Befehls betrifft, nehmen wir die Anzahl der Zeichen bis zur ersten Ziffer Modulo 7. Für Addition ist dies 4 (einschließlich des folgenden Leerzeichens), für Subtraktion ist es 2, für Division durch 3, für Multiplikation durch 5 und für subtrahieren von es 0. Das Subtrahieren von erfordert ein wenig zusätzliche Behandlung, da es das benötigt
\-
Befehlskombination , aber die anderen verwenden nur ihren Wert, um das entsprechende Befehlszeichen in einer Tabelle zu suchen.Dieser Vorgang wird für jeden Befehl wiederholt, wobei die Ausgabe in einer vorkonstruierten Zeichenfolge in Zeile 8 aufgebaut wird. Jedes Mal, wenn ein zusätzlicher Befehl hinzugefügt wird, wird der Zeichenfolge ein schließendes Anführungszeichen hinzugefügt, um sicherzustellen, dass sie immer ordnungsgemäß terminiert ist. Wenn wir schließlich das Ende unserer Eingabe erreichen, "führen" wir einfach diesen String aus, um ihn auf den Stapel zu schieben, und folgen ihm mit einer Standardausgabesequenz, um alles auszuschreiben.
quelle
JavaScript (ES6), 163 Byte
Versuch es:
quelle
Vim
208171168 BytesEs wurde die Möglichkeit hinzugefügt, mehrere Wiederholungen nacheinander gemäß @ Flp.Tkc auszuführen, aber es wurden genügend Bytes abgelegt, sodass ich die Byteanzahl immer noch senken konnte.
TryItOnline
Nicht druckbare Zeichen:
Testfallausgabe:
cw^R=^R" ^[
TryItOnlinecw^R=((^R" /5) *-1+9) ^[
TryItOnlinecw^R=((((((^R" +5) +10) *2) -15) -15) /2) ^[
TryItOnlinequelle
Lex, 246 Bytes
Lex zielt auf C ab, daher müsste ein C-Compiler es in eine ausführbare Datei kompilieren. Die Lexer-Bibliothek (
ll
) müsste ebenfalls verlinkt werden. Dies kann eine Byte-Strafe hinzufügen, aber ich bin nicht sicher, wie viele Bytes, wenn ja.Das Programm gibt ein Lex-Programm (gemäß Spezifikation) aus, das den transpilierten Wordmath-Ausdruck auswertet. Der Code zwischen
%{
und%}
ist nur für den "Transpiler":Zwischen den beiden
%%
Zeilen befindet sich der Regex / Action-Teil. Die erste Regel, die gefunden wird, istT
("Think ..."), die die Präambel erstellt (Lex-Programme müssen mindestens den Regelabschnitt enthalten, undyytext
letzte übereinstimmende Text sein, sodass die Regel den Akkumulator im Wesentlichen mit den Eingaben des Benutzers verbindet ).Das Programm verwirft alle Eingaben mit Ausnahme derjenigen , die abgestimmt ist, und die anderen Regeln (
ad
,fr
bis zure
) behandeln die wordmath Ausdruck Klauseln als minimal ein Spiel wie möglich eindeutig zu sein. In den meisten diese, setzt sichc
auf einen Ausdruck Infix, die zwischen konkateniert wirdn
und die letzte Ganzzahl gelesen , wennO
aufgerufen wird (so beispielsweise das Lesen „add 9“ wird die Infix einzustellen+=
, v9
, und der Anruf anO
Willen Ausgangn+=9;
) . (Interessanterweise führt "subtrahieren von 8" dazu, dass sowohl die Regelns
als auch diefr
Regeln übereinstimmen. DaO
jedoch nur die Zahl aufgerufen wird, ist die richtige Regeln=-n+8;
der einzige Ausdruck, der ausgegeben wird.) Dasre
Regel für "Wiederholen" nennt man einfachO
Auch hier wird der zuletzt erstellte Ausdruck ausgegeben (und da nachfolgende Übereinstimmungen nicht mehr funktionierenyytext
, war die Ganzzahlkonvertierung in der[0-9]+
Regel erforderlich , da "repeat" unterstützt wird ). Schließlich bewirkt eine Periode die Ausgabe des Programm-Trailers, der nur den Akkumulator ausgibt und mit dem%%
Paar schließt, das das Ende des Ausgabe-Lex-Programms bezeichnet.Hinweis: Weder das Haupttranspilerprogramm noch das Ausgabeprogramm werden beendet. Das Leiten von Eingaben in würde funktionieren oder EOF (Strg-D) bereitstellen. Wenn nach der ersten Eingabe eine Beendigung erforderlich ist, können exit () s hinzugefügt werden.
Zum Bauen / Laufen:
Test 1:
Test 2:
Test 3:
Test 4:
quelle
Pyth,
6967 BytesEin Programm, das die Eingabe von a
"quoted string"
und das Ergebnis druckt.Testsuite
Wie es funktioniert
Pyth hat Präfixoperatoren, daher werden die grundlegenden arithmetischen Operationen mit ausgeführt
(operator)(operand1)(operand2)
, während die vorinitialisierte VariableQ
die Eingabe liefert. Daher wird ein transpiliertes WordMath-Programm erstellt, indem mit der Zeichenfolge begonnen'Q'
wird und in jeder Phase der Operator vorangestellt und dann der Operand nach Bedarf vorangestellt oder angehängt wird.J\Q
Setzen SieJ
den transpilierten Programmstring auf den String'Q'
tcQ\,
Teilen Sie die Eingabe durch Kommas und verwerfen Sie das erste Element (das ist 'Think of a number'
)V
DennN
darin:Iq@N1\r
Wenn das Zeichen anN[1]
ist'r'
(Wiederholung):=NZ
SetzenN
aufZ
(vorheriger Wert vonN
, setzen am Ende der for-Schleife)x"asdm"@N1
Finden Sie den Index vonN[1]
in"asdm"
(addieren, subtrahieren, dividieren, multiplizieren)@"+-/*"
Indizieren Sie damit in"+-/*"
und geben Sie den erforderlichen Operator an,J-eCN)\.
Ergibt die Liste mit zwei Elementen[J, -eCN)\.]
, wobei das zweite Element das letzte Element derN
Aufteilung in Leerzeichen ist, wobei alle'.'
Zeichen entfernt wurden (Operand).qh@cN)1\f
Wenn das erste Zeichen des zweiten ElementsN
auf Leerzeichen aufgeteilt ist'f'
(subtrahieren von):.>
Tauschen Sie die Elemente der Liste mit zwei Elementen aus+
Führen Sie den Operator und die Liste mit zwei Elementen in einer Liste zusammen=Jjd
einstellenJ
Sie zu , dass auf Räume verbunden=ZN
Stellen SieZ
aufN
J
DruckenJ
quelle
Pip , 58 Bytes
Schade, dass ich diesen Rückwärtssubtraktionsoperator noch nicht implementiert habe.
Das Programm nimmt ein WordMath-Skript von stdin und gibt Pip-Code an stdout aus. Der ausgegebene Code nimmt auf ähnliche Weise eine Zahl von stdin und gibt das Ergebnis an stdout aus. Probieren Sie es online!
Strategie
Für Eingaben wie diese:
wir wollen folgendes ausgeben:
was wie folgt funktioniert:
Ungolfed + Erklärung
Die Grundstruktur des Programms ist
{...}Mq^k
, das sichq
(eine Zeile von stdin) aufteiltk
M
jedes Element (Komma-Leerzeichen) aufgespalten wird und eine Funktion zugewiesen wird.Innerhalb der Funktion beginnen wir mit der Behandlung des
repeat
Falls. Der kürzeste Test in Pip scheint zu seinsNa
(gibt es ein Leerzeichen im Befehl). Wenn ja, möchten wir verwendena
; Wenn nicht, verwenden Siep
, um den vorherigen Befehl zu speichern. Weisen Sie diesen Wert wieder zua
und auch zup
(für das nächste Mal).Für unseren Rückgabewert verwenden wir eine Liste, was in Ordnung ist, da das Standardausgabeformat für Listen darin besteht, alles miteinander zu verketten. Das Ergebnis beginnt immer mit
Y
. Als nächstes benötigen wir eine Nachschlagetabelle für die Operationen.Beachten Sie, dass die Längen von
add
(4),subtract
(9),divide by
(10),multiply by
(12) undsubtract from
(14) alle unterschiedlich sind. Beachten Sie weiterhin, dass sie in Mod 7 immer noch unterschiedlich sind. Daher können Sie sie verwenden, um eine Liste mit sieben Elementen zu indizieren (die fünf Codeausschnitte und zwei Platzhalter enthält), um jeden WordMath-Befehl dem entsprechenden Pip-Code zuzuordnen (entsprechend der Nummer) kann einfach bis zum Ende verkettet werden):-y+
(subtract from
)y-
(subtract
)y//
(divide by
)y+
(add
)y*
(multiply by
)Für die Indizes verwenden regex wir den Index der ersten Ziffer in dem Befehl zu erhalten:
a@?`\d`
. Wir reißen den Regex auchy
für die zukünftige Verwendung ein. Die Nachschlagetabelle wird durch Aufteilen der Zeichenfolge"-y+ y- y// y+ y* "
aufs
(Leerzeichen) generiert .Wir müssen noch den ersten Eintrag bearbeiten, der in den Code übersetzt werden soll
Yq
. DaThink of a number
keine Ziffern enthalten sind, gibt der@?
Operator nil zurück. Die Verwendung von nil als Index in der Nachschlagetabelle gibt ebenfalls nil zurück. Nil ist falsch, daher müssen wir für diesen Fall nur add|'q
to useq
anstelle einer Operation ausführen.Das letzte Element der zurückgegebenen Liste ist die Nummer selbst. Wir erhalten dies über
a@y
(finden Sie alle Übereinstimmungen im Befehl der zuvor gezerrten Regex). Dies gibt eine Liste mit Ziffern zurück, aber auch dies ist kein Problem, da alle Listen bei der Ausgabe verkettet werden. Für den ersten Eintraga@y
nicht mit Ziffern überein und gibt eine leere Liste aus, die der Ausgabe nichts hinzufügt.Beispielsweise
Mit Eingabe
Der Kartenausdruck gibt die Liste an
was, wenn verkettet, ausgibt
quelle
Python 2 ,
154153146 BytesBehoben und dabei sogar mehrere Bytes gespeichert. ^ __ ^
Probieren Sie es online!
Basiert auf der gleichen Strategie wie meine Pip-Antwort . Python-spezifische Funktionen:
Think of
und das Schließen.
werden vor dem Teilen von der Zeichenfolge entfernt (input()[9:-1]
) . Die Periode war zu lästig, um sie in der Hauptschleife zu verarbeiten. Das Entfernen der ersten neun Zeichen hilft aus einem anderen Grund (siehe unten).import re
), wirdrfind(" ")
der letzte Platz im Befehl gesucht . Wir können dies auch verwenden, um nach dem zu suchenrepeat
Fall .a number
, in dem sich der Index des Leerzeichens befindet1
. Dieser Index füllt bequemerweise die andere Lücke in der Nachschlagetabelle. Das andere Problem bei der Verarbeitung der Eingangsstufe in der Hauptschleife war der+c[s:]
Teil, der dazu führen würdex=input() number
. Um dieses Problem zu lösen, multiplizieren wir die Zeichenfolge mitc[0]<"a"
:1
für alle regulären Befehle, in denenc
mit einem Leerzeichen begonnen wird, aber0
für die Initialea number
.quelle
WinDbg,
449388 Bytes-61 Bytes durch Definieren eines Alias für wiederholten Code
Inspiriert von LambdaBetas Einsatz von
#define
. Dieser Ansatz ändert die WordMath-Syntax geringfügig (,
und.
muss wie die anderen Wörter und durch Leerzeichen getrennt werden),
folgt nichtrepeat
) und erstellt einen Alias, sodass die geänderte WordMath-Syntax gültiger WinDbg-Code ist. In der letzten Zeile wird die Frage beantwortet und transpiliert, indem die Eingabe in die geänderte Syntax konvertiert wird.Die Eingabe erfolgt durch Setzen eines Strings an einer Speicheradresse und Setzen des Pseudoregisters
$t0
auf diese Adresse. Hinweis: Dadurch wird dasint
at0x2000000
überschrieben. Wenn Sie also dort mit der Eingabe beginnen, wird es teilweise überschrieben.$t0
wird auch überschrieben.Da Aliase erstellt werden, ist der Ausgabecode je nachdem, ob dieser Code vor oder nach dem Festlegen der Zeichenfolge ausgeführt wurde, unterschiedlich (entweder mit Alias oder ohne Alias). Leider habe ich keine Möglichkeit gefunden, die Aliase ordnungsgemäß zu erweitern, ohne durch Leerzeichen getrennt zu sein.
Wie es funktioniert:
Beispielausgabe, Eingabe der Zeichenfolge, bevor dieser Code einmal ausgeführt wird (das resultierende Programm ähnelt WordMath):
Beispielausgabe, Eingabe der Zeichenfolge nach einmaliger Ausführung dieses Codes (die Aliase werden bei der Eingabe der Zeichenfolge erweitert, damit das resultierende Programm nicht so schön ist):
Noch ein paar Beispiele, nur mit der leicht geänderten WordMath-Syntax:
quelle
Scala, 338 Bytes
Probieren Sie es selbst bei ideone
Erläuterung:
quelle