Römische Zahlen

In einem Internet-Wettbewerb bin ich über die Herausforderung gestolpert, in möglichst wenig Code eine saubere Funktion zur Umrechnung von römischen Zahlen ins mittlerweile doch schon etwas länger übliche Dezimalsystem zu schreiben. Da eine meiner größten Schwächen ist, solche Herausforderungen fast blind anzunehmen, konnte ich natürlich nicht widerstehen.

Zwei Stunden später war folgende PHP-Funktion fertig:

[php]
<?php
function roman_to_decimal($roman) {
// definie the roman values
$a=array(0=>array("I"=>1, "V"=>5, "X"=>10, "L"=>50, "C"=>100, "D"=>500, "M"=>1000));
// clean up the given statement – you’ll never know…!
$roman = trim(strtoupper($roman));
// make an array out of the given statement
$x=str_split($roman);
$l=strlen($roman)-1;
// convert letters to numbers
for($y=0;$y<=$l;++$y) { $x[$y]=$a[0][$x[$y]]; }
// do the math work…
for($y=0;$y<=$l;++$y) {
if($x[$y]<$x[$y+1]) { $x[$y]*=-1; }
$r+=$x[$y];
}
// return calculated value
$decimal = "nullum";
if ($r>0) { $decimal = $r; }
return $decimal;
}
// ————————————————-
// how to use it…
// ————————————————-
$r = "MCXXX";
echo "Roman: ".$r." — Decimal: ".roman_to_decimal($r); ?>
[/php]

Zusammengeschrumpft hat die Funktion dann ca. 250 Bytes – ich persönlich fand das nicht schlecht. Andere Funktionen waren jedoch lediglich nur halb so groß! Wie soll das bloß gehen? Naja, zumindest funktioniert meine Funktion einwandfrei… ist ja auch etwas wert!


Beitrag veröffentlicht

in

von

Schlagwörter:

Kommentare

13 Antworten zu „Römische Zahlen“

  1. Avatar von Björn

    Ohne Mathe stimmt nicht ganz! Aber trotzdem eine prima Lösung!

  2. Avatar von Joscha
    Joscha

    Nach wieder einigen Jahren.. ein ganz anderer Ansatz und ganz ohne Mathe:
    function r($r){
    $a=array(„IV“,“IX“,“XL“,“XC“,“CD“,“CM“,“I“,“V“, „X“, „L“,“C“,“D“,“M“);
    $b=array(„4+“,“9+“,“40+“,“90+“,“400+“,“900+“,“1+“,“5+“,“10+“,“50+“,“100+“,“500+“,“1000+“);
    $b=str_ireplace($a,$b,$r).“0″;
    return eval(„return $b;“);}

    Viele Grüße,
    Joscha

  3. Avatar von Björn

    Hehe, mein Code ist drei Jahre alt, ist innerhalb von etwa 60min an einem viel zu frühen Samstag Vormittag entstanden. Vielen Dank für die guten Ergänzungen!

  4. Avatar von DomiX
    DomiX

    $a=array(0=>array(„I“=>1, …
    Wozu ist in diesem array noch ein array?
    Dadurch hast du in der for Schleife
    $a[0][$x[$y]]

    Ein array wie „$a=array(„I“=>1…“ würde ausreichen und in der for-Schleife dann ‚$a[$x[$y]]‘ verwenden ist viel kürzer.

    $r sollte auch vor der Schleife deklariert werden
    und in der Zeile
    if($x[$y]<$x[$y+1]) { $x[$y]*=-1; }
    wird beim letzten Element im array $x mit $x[$y+1] auf ein nicht existierendes Index zugegriffen. Sollte vorher auf Existenz geprüft werden.
    Mit return $r ? $r : $decimal; sparst du dir wieder die if Abfrage davor.

  5. Avatar von Bambuu
    Bambuu

    Jetzt habe ich alles verstanden.
    Danke für die schnelle antwort 🙂

  6. Avatar von Björn

    if($x[$y]<$x[$y+1]) <<- Warum +1?
    {
    $x[$y]*=-1;
    <<-Warum *=1? Was heißt das?

    Der Dezimalwert von römische Zahlen ist abhängig von der Positionierung. Um nun festzustellen, wie ich mit der Zahl zu rechnen habe, muss ich diese also mit dem Wert der nächsten Zahl vergleichen. Beispiel XI und IX. Bei XI rechne ich 10 + 1 (=11). Wenn aber nun 1 vor der 10 steht (IX) dann muss ich den Wert der vorangegangenen Ziffer abziehen. Die if-Klausel prüft, ob der vorangestellte Wert kleiner ist, das *=-1 dreht das Vorzeichen in diesem Fall, sodass in das Ergebnis $r nur noch den Wert addiert werden muss.

    $l=strlen($roman)-1; <<- warum -1?

    Die Länge der Zeichenfolge benötige ich für den Berechnungsloop (die for-Schleifen). Wenn ich -1 weglassen würde, dann müsste ich die for-Kommandos auf for($y=0;$y<$l;++$y) verändern. Warum ich das damals so gemacht habe, weiß ich nicht mehr so genau, aber es sollte beides gehen – und es gibt sicherlich noch bessere Methoden, die Länge zu ermitteln.

  7. Avatar von Bambuu
    Bambuu

    Ja , das habe ich soweit verstanden.
    Was ich nicht ganz verstehe ist der mathetische teil.

    // do the math work…
    for($y=0;$y<=$l;++$y)
    {
    if($x[$y]<$x[$y+1]) <<- Warum +1?
    {
    $x[$y]*=-1; <<-Warum *=1? Was heißt das?
    }
    $r+=$x[$y];
    }

    Und

    $l=strlen($roman)-1; <<- warum -1?

    Tut mir leid, wenn die fragen etwas doof sind, aber ich bin nueling in den thema php und meine kenntnisse sind sehr begrenzt.

  8. Avatar von Björn

    Hallo Bambuu,

    naja, Sinn der Übung war damals (und das ist schon zwei Jahre her), einen möglichst komprimierten Code zu haben. Prinzipiell hat der Codeblock fünf Bestandteile:
    1) Definition der Römischen Zeichen,
    2) Vorbereiten des Input und Wandeln in ein Array,
    3) Wandeln der Zeichen in die korrespondierenden Zahlen,
    4) Wert berechnen,
    5) Rückgabe.

    Wo genau verstecken sich Ihre Verständnisfragen?

    Grüße,
    Björn

  9. Avatar von Bambuu
    Bambuu

    Könnten sie vllt. eine vollständige erklärrung für jeden schritt einfügen, da ich nicht ganz verstehe was sie dort gemacht haben.

  10. Avatar von Björn

    Die Herausforderung kam damals von codegolf.com, einer Seite, die mehr oder weniger regelmäßig solchen Programmierthemen widmet.

  11. Avatar von Arno Nym
    Arno Nym

    Hm, waere jetzt noch interessant die anderen Ergebnisse zu sehen – gibts die Contestdaten auf irgendner Website zu bestaunen?

  12. Avatar von LILLI
    LILLI

    hi ich lobe dich

  13. Avatar von Lerntipps

    Grosses Lob von meiner Seite, dein Blog gefaellt mir sehr gut
    Hoffentlich folgen noch weitere Beitraege, ich bin auf jedenfall gespannt
    Viele Gruesse, Simon

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.