Die Herausforderung besteht darin, alle römischen Ziffern in der von Ihnen gewählten Sprache als gültigen Code zu kennzeichnen.
Sie sollten nicht in Strings oder Ähnlichem vorkommen, sondern wie alle anderen Token, Literale wie ( arabische ) Zahlen, Zeichen oder Strings funktionieren . oder Variablen- / Methoden- / Funktionsbezeichner usw.
In Java müsste beispielsweise Folgendes so kompiliert und ausgeführt werden, als ob i
es initialisiert worden wäre 42
:
int i = XLII;
Das eigentliche Parsen der Ziffern ist zweitrangig, sodass Sie eine Bibliothek verwenden können, wenn Sie möchten. Dies ist jedoch ein Beliebtheitswettbewerb, sodass Kreativität gefördert wird.
Sie können keine Sprache verwenden, die tatsächlich römische Ziffern verwendet, wenn es so etwas gibt.
Viel Glück.
Process
ast
dem die Quelle analysiert wird. Fügen Sie am oberen Rand des AST die Definition der römischen Ziffern von 1 bis 3999 ein. Kompilieren Sie das Ganze und führen Sie es aus. Es ist nur langweilig, den Code zu schreiben, um den Prozess zu handhaben.Antworten:
C
Es gibt nur so viele römische Ziffern, da 4000 und höher keine Standardnotation haben, und der Präprozessor ist ein wunderbares Dekomprimierungswerkzeug, besonders wenn Sie keine Probleme damit haben, dass der Code undefiniertes Verhalten aufweist.
Dies definiert alle römischen Ziffern von
I
bisMMMCMXCIX
als Aufzählungskonstanten plus_
(die durch beliebiges ersetzt werden können) als Null.quelle
scanf
auch :) @ klingt.net Ich bin nicht sicher, was für ein Beispiel Sie suchen. Ein ziemlich einfaches wäreint main() { return MMMCMXCIX - M - M - M - CM - XC - IX; }
Rubin
Alle (Groß-) römischen Ziffern werden nun wie ihre Dezimaläquivalente analysiert. Das einzige Problem ist, dass sie noch zuweisbar sind: Sie können es tun
X = 9
, aber nicht10 = 9
. Ich glaube nicht, dass es einen Weg gibt, das zu beheben.quelle
JavaScript (ES6)
Verwenden Sie
Proxy
, um römische Ziffern zu fangen.Testbar in Firefox (aktuell) auf JSFiddle .
In Chrome (mit Traceur) nicht testbar, da die
Proxy
Implementierung fehlerhaft ist.Verwendung:
quelle
C & C ++ (aktualisierte Antwort)
Wie in einem Kommentar festgestellt, hatte meine ursprüngliche Lösung zwei Probleme:
Da ich wollte, dass mein Code so allgemein wie möglich ist, um auf älteren Plattformen zu arbeiten, beschloss ich, es noch einmal zu versuchen. Es ist länger als zuvor, funktioniert jedoch auf Compilern und Präprozessoren, die auf den Kompatibilitätsmodus C89 / C90 eingestellt sind. Allen Makros wird eine angemessene Anzahl von Argumenten im Quellcode übergeben, obwohl diese Makros manchmal zu nichts "expandieren".
Visual C ++ 2013 (auch bekannt als Version 12) gibt Warnungen über fehlende Parameter aus, aber weder mcpp (ein Open-Source-Präprozessor, der hohe Übereinstimmung mit dem Standard behauptet) noch gcc 4.8.1 (mit -std = iso9899: 1990 -pedantic-errors-Schaltern) Warnungen oder Fehler für diese Makroaufrufe mit einer effektiv leeren Argumentliste.
Nach Durchsicht der relevanten Norm (ANSI / ISO 9899-1990, 6.8.3, Macro Replacement) besteht meines Erachtens hinreichende Unklarheit, dass dies nicht als Nicht-Norm angesehen werden sollte. "Die Anzahl der Argumente in einem Aufruf eines funktionsähnlichen Makros muss mit der Anzahl der Parameter in der Makrodefinition übereinstimmen ...". Es scheint eine leere Argumentliste nicht auszuschließen, solange die erforderlichen Klammern (und Kommas bei mehreren Parametern) vorhanden sind, um das Makro aufzurufen
Das Problem mit dem nachstehenden Komma wird gelöst, indem der Aufzählung ein zusätzlicher Bezeichner hinzugefügt wird (in meinem Fall MMMM, der für den Bezeichner so sinnvoll wie alles andere zu sein scheint, als 3999 zu folgen, auch wenn er nicht den anerkannten Regeln der römischen Ziffernfolge entspricht genau).
Eine etwas sauberere Lösung würde darin bestehen, die Aufzählung und die unterstützenden Makros in eine separate Header-Datei zu verschieben, wie in einem Kommentar an anderer Stelle impliziert, und die Undef der Makronamen unmittelbar nach ihrer Verwendung zu verwenden, um eine Verschmutzung des Namespace zu vermeiden. Zweifellos sollten auch bessere Makronamen gewählt werden, dies ist jedoch für die jeweilige Aufgabe angemessen.
Meine aktualisierte Lösung, gefolgt von meiner ursprünglichen Lösung:
Die ursprüngliche Antwort (die die ersten sechs Upvotes erhalten hat, falls dies also noch einmal von niemandem bewertet wird, sollten Sie nicht glauben, dass meine aktualisierte Lösung die Upvotes erhalten hat):
Im gleichen Sinne wie eine frühere Antwort, jedoch auf eine Weise, die nur mit definiertem Verhalten portierbar sein sollte (obwohl sich unterschiedliche Umgebungen in einigen Aspekten des Präprozessors nicht immer einig sind). Behandelt einige Parameter als optional, ignoriert andere, sollte auf Präprozessoren funktionieren, die das
__VA_ARGS__
Makro nicht unterstützen , einschließlich C ++. Verwendet indirekte Makros, um sicherzustellen, dass die Parameter vor dem Einfügen des Tokens erweitert werden. es ist zwar immer noch schwierig und wahrscheinlich nicht leicht zu lesen, aber einfacher):quelle
__VA_ARGS__
.Common Lisp
Das Folgende ist eine ziemlich lange Erklärung, wie ich ein Makro erstellt habe, das Sie so verwenden können:
Wenn ein Makro in Common Lisp aufgerufen wird, verhält es sich im Grunde genommen wie eine Funktion, nur dass die Argumente empfangen werden, bevor sie ausgewertet werden. Da es sich bei Common Lisp-Code nur um Daten handelt, erhalten wir eine (verschachtelte) Liste, die einen nicht analysierten Syntaxbaum darstellt, mit dem wir alles tun können, was wir wollen, und dies geschieht in der Kompilierungszeit.
Hilfsfunktionen
Der erste Schritt des Plans besteht darin, diesen Baum auf alles zu scannen, was wie römische Ziffern aussieht. Da dies Lisp und alles ist, wollen wir versuchen, es etwas funktionaler zu machen: Wir brauchen eine Funktion, die einen Baum tief durchläuft und jedes Objekt
searchp
zurückgibt, für das eine bereitgestellte Funktion true zurückgibt. Dieser ist sogar (halb-) schwanzrekursiv.Dann ein Code zum Parsen der römischen Ziffern, mit freundlicher Genehmigung von Rosetta Code :
Das eigentliche Makro
Wir nehmen den Syntaxbaum (
body
), durchsuchen ihn mit unserem Deep-Find-All-Verfahren und stellen die gefundenen römischen Ziffern irgendwie zur Verfügung.Also, was ist das
1 + 2 + 3 + (4 * (5 + 6)) + 7
?Und um zu sehen, was tatsächlich passiert ist, als das Makro aufgerufen wurde:
quelle
Lua
Einfach ein Fallback-Index für die globale Tabelle. Die eigentliche Konvertierung mit gsub fiel viel hübscher aus, als ich es mir vorgestellt hatte.
quelle
Nachsatz
Ich habe versucht, dem C zu folgen, aber ich habe es nicht verstanden. Also habe ich es so gemacht:
Postscript hat keine,
enum
aber wir können ein Wörterbuch mit sequentiellen Ganzzahlwerten erstellen und diese in ein Array falten. Dies reduziert das Problem, alle Zeichenfolgen nacheinander zu generieren, indem 4 verschachtelte Schleifen verkettet werden. Es generiert also alle Zeichenfolgen und verschachtelt jede Zeichenfolge mit einem ansteigenden Zählerwert. Dies führt zu einer langen Reihe von <string> <int> -Paaren auf dem Stapel, die in<<
... eingebunden sind>>
, um ein Dictionary-Objekt zu erstellen.Das Programm erstellt und installiert ein Wörterbuch, in dem alle Namen der römischen Ziffern dem entsprechenden Wert zugeordnet sind. Das Erwähnen der Namen im Quelltext ruft also die automatische Namenssuche auf und liefert den ganzzahligen Wert auf dem Stapel.
druckt
quelle
Smalltalk (Smalltalk / X) (87/101 Zeichen)
Natürlich könnten wir den Tokenizer des Parsers leicht modifizieren (da er Teil der Klassenbibliothek ist und als solcher für Modifikationen offen und immer vorhanden ist), aber eine Herausforderung besteht darin, nur Evaluierungen in einem gegebenen Kontext zu beeinflussen, so dass der Rest des Parsers System funktioniert wie gewohnt.
Version 1:
Definieren Sie eine Reihe von Variablen im Auswertungs-Namespace. Dies wirkt sich also auf interaktive Aufgaben (auch bekannt als evals) aus:
dann kann ich (in einem doIt, aber nicht in kompiliertem Code) tun:
-> 2019
Hinweis: Die 101 Zeichen enthalten Leerzeichen. Eigentlich kann es mit 87 Zeichen gemacht werden.
Beachten Sie auch, dass beim Definieren im globalen Smalltalk-Namespace diese Konstanten auch in kompiliertem Code angezeigt werden.
Version 2:
Verwenden Sie einen methodWrapper-Hook, mit dem vorhandener Code ohne Neukompilierung umbrochen werden kann. Der folgende Befehl umschließt den Tokenizer des Parsers, um nach einer römischen ID zu suchen, die gescannt werden soll, und macht sie zu einer Ganzzahl. Der schwierige Teil besteht darin, dynamisch zu erkennen, ob der aufrufende Kontext aus dem römischen Reich stammt oder nicht. Dies geschieht mit einem Abfragesignal (was technisch eine verfahrensfähige Ausnahme darstellt):
Definieren Sie die Abfrage:
Daher können wir jederzeit ("InRomanScope-Abfrage") darum bitten, standardmäßig false zu erhalten.
Wickeln Sie dann die checkIdentifier-Methode des Scanners ein:
Jetzt funktioniert der Scanner wie gewohnt, es sei denn, wir befinden uns im römischen Reich:
-> 2525
Wir können sogar Code kompilieren:
netter Versuch; Dies schlägt jedoch mit einem Syntaxfehler fehl (was genau das ist, was wir wollen). Im römischen Reich KÖNNEN wir jedoch kompilieren:
und jetzt können wir eine beliebige Ganzzahl (die diese Nachricht sendet) von innerhalb und außerhalb Roms fragen:
-> 2525
quelle
Haskell mit Meta-Programmierung in Template Haskell und römischen Ziffern :
Haskell reserviert Bezeichner, die mit Großbuchstaben beginnen, für Konstruktoren, daher habe ich Kleinbuchstaben verwendet.
quelle
J - 78 Zeichen
Dies gilt wie bei den anderen Lösungen nur für MMMCMXCIX = 3999.
Zerlegen (Rückruf J wird normalerweise von rechts nach links gelesen, sofern nicht durch Klammern ersetzt):
M`CDM`XLC`IVX
- Vier Briefkästen. Wir werden numerische Arrays als Index für diese Buchstaben verwenden und Unterwörter aus römischen Ziffern aufbauen.841,3#79bc5yuukh
- Dies sind die numerischen Daten, fest codiert. *(_1,~3#.inv])
- Dies dekodiert die obigen Daten, indem es ternär erweitert und -1 angehängt wird.('';&;:(...){' ',[)&.>
- Kombinieren Sie die Zahlen auf der linken Seite mit den Feldern auf der rechten Seite (&.>
), dekodieren Sie die Zahlenfelder und verwenden Sie sie, um die Buchstaben zu indizieren. Wir behandeln 0 als Leerzeichen, indem wir den Buchstabenlisten ein Leerzeichen voranstellen. Diese Prozedur erstellt Listen mit Wörtern wieI II III IV V VI VII VIII IX
undM MM MMM
.{
- Nehmen Sie das kartesische Produkt dieser vier Schachteln voller Wörter. Jetzt haben wir ein 4D Array aller römischen Ziffern.}.,;L:1
- Führen Sie all dies in einer einzigen 1D-Liste mit römischen Ziffern aus und entfernen Sie die leere Zeichenfolge an der Vorderseite, da dies zu einem Fehler führen würde. (L:
ist ein seltener Anblick in J Golf! Normalerweise sind nicht so viele Levels des Boxens involviert.)}.i.4e3
- Die Ganzzahlen von 0 bis 4000, ohne die Endpunkte.=:
. Mit J können Sie eine Box-Liste mit Namen auf der LHS als eine Form der berechneten Mehrfachzuweisung haben, damit dies gut funktioniert.Jetzt ist der J-Namespace voll mit Variablen, die römische Ziffern darstellen.
* Ich brauche die Nummer 2933774030998, um sie später in der Basis 3 lesen zu können. Es kommt vor, dass ich sie in der Basis 79 mit Ziffern von maximal 30 ausdrücken kann az). Dadurch werden 3 Zeichen über dem Komma gespeichert.
quelle
Python
Die Idee ist einfach wie die anderen Antworten. Aber nur um ordentlich zu sein und den globalen Namespace nicht zu verschmutzen, wird ein Kontextmanager verwendet. Dies beinhaltet auch die Einschränkung, dass Sie vorab den Umfang der römischen Zahlen, die Sie verwenden möchten, deklarieren müssen.
Hinweis Um es einfach zu halten und das Rad nicht neu zu erfinden, habe ich das römische Python-Paket verwendet
Implementierung
Demo
quelle
Python
Dies ist möglicherweise die einfachste Lösung mit Python:
quelle
globals()[var] = value
alsexec()
.D
unter Verwendung der Auswertung der Kompilierzeitfunktion von D
quelle
APL (Dyalog APL) , 77 Bytes
Fordert zur Eingabe der maximalen Länge der römischen Zahl auf und definiert alle Variablen.
t←
t bekommt'IVXLCDM',
Römische Zeichen gefolgt von⊂
eine geschlossene⍬
leere Listet[
…]
Index t mit…⍉
die transponierte (um die richtige Reihenfolge zu bekommen)8⊥⍣¯1
geeignete Breite Basis-Acht-Darstellung von⍳
die ersten n Indizes, wobei n ist¯1+
einer weniger als8*⎕
acht hoch numerische Eingabe,/
Zeilen abflachen (jede Darstellung){
...}¨
wende die folgende anonyme Funktion auf jede Darstellung an ...(
…)[t⍳⍵]
Entsprechend den Positionen der Argumente in t wählen Sie aus…∊
die eingetragenen1 5∘ר
jeweils ein- und fünfmal10*
zehn hoch⍳4
null bis drei0,⍨
Null anhängen2(…)/
Wenden Sie auf jedes Schiebefenster der Länge 2 den folgenden anonymen Funktionszug an…⊣×
das linke argument mal¯1*
negativ hoch hoch<
ob das linke Argument kleiner als das rechte Argument ist+/
Summe⍵'←',
Stellen Sie das Argument (die römische Ziffer) und einen Zuweisungspfeil voran⍕
Formatieren (um die Zahl zu reduzieren und in Text umzuwandeln)⍎
führe das aus (macht die Zuweisung außerhalb der anonymen Funktion)Probieren Sie es online! (mit maximaler Länge 5)
quelle
PHP
Es gibt mehrere Regeln für gültige römische Zahlen
Schreiben Sie den größten Wert vor die niedrigeren Werte
Subtrahieren Sie nur
[I,X,C]
vor den nächsten 2 größeren WertenSubtrahieren Sie double
[I,X,C]
vor den nächsten 2 größeren WertenSubtrahieren Sie double
[I,X,C]
vor den größeren WertenKombiniere 4 + 5
Online Version
Schritt 1 Erstellen Sie die Regeln
ist die JSON-Ausgabe für alle gültigen römischen Zahlen
Schritt 2 Erstellen Sie Listen für alle Regeln bis 3999
Schritt 3 Erstellen Sie Konstanten
Kombinieren Sie alle Listen und definieren Sie Konstanten
Ausgabe
Im Beispiel multiplizieren Sie zwei gültige Versionen der Nummer 8
quelle
Rebol
Beispiel
Ausgabe:
Haftungsausschluss: Ich bin sicher, dass es auch in Rebol andere (und wahrscheinlich bessere!) Möglichkeiten gibt, dies zu tun.
PS. Meine
roman-to-integer
Funktion ist eine Transliteration des netten Ruby-Algorithmus von Histocrat zum Umwandeln einer Zeichenfolge mit römischen Zahlen in eine Zahl. Mit Dank zurückgekehrt! +1quelle
Lua
Dies wirkt sich auf die Metatabelle der globalen Tabelle aus und gibt ihr eine neue Indexfunktion. Wenn eine globale Variable abgefragt wird, die nur römische Ziffern enthält
XVII
, analysiert sie sie beispielsweise.Einfach zu testen;
Probieren Sie es online!
quelle
VBA, 204 Bytes
Ein erklärtes Unterprogramm , das keine Eingabe erfolgt, und wenn ausführen, erstellt das
public
ly zugänglichEnum
,R
, die alle der römischen Ziffer Werte enthält. Diese Werte können direkt verwendet werden, ohne auf die Enumeration zu verweisen.Aufzählungshaltewerte von 1 bis 3999.
Hinweis: Die Terminals
"
in den Zeilen 3 und 7 dienen nur der Hervorhebung der Syntax und tragen nicht zum Bytecount beiUngolfed und erklärt
quelle