11
Feb

Römische Zahlen

categories PHP    

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
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);  ?>

 

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!

Kommentare

Comments (9) - “Römische Zahlen”

  1. Lerntipps am 12.02.2008 um 16:13 Uhr 

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

  2. LILLI am 08.06.2008 um 16:26 Uhr 

    hi ich lobe dich

  3. Arno Nym am 14.10.2009 um 23:24 Uhr 

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

  4. Björn am 15.10.2009 um 08:11 Uhr 

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

  5. Bambuu am 16.06.2010 um 10:50 Uhr 

    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.

  6. Björn am 16.06.2010 um 11:20 Uhr 

    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

  7. Bambuu am 17.06.2010 um 08:30 Uhr 

    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. Björn am 17.06.2010 um 09:07 Uhr 
    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.

  9. Bambuu am 17.06.2010 um 09:11 Uhr 

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

Hinterlasse einen Kommentar!




WP SlimStat