Römische Zahlen
Dieses Skript hat eine lange Geschichte. Vor vielen Jahren wurde mir im Informatikunterricht die Aufgabe gestellt, einen Konverter zwischen römischen und arabischen Dezimalzahlen in Pascal zu schreiben.
Das habe ich damals gemacht. Einige Jahre später hätte ich das alte Skript gebraucht – es war weg. Das hat mich so geärgert, dass ich nicht ruhen konnte, bis ich den Code in Perl repliziert hatte.
Zwei Tage, nachdem das Skript zu meiner Zufriedenheit funktionierte, warf ich einen Blick ins Perl Cookbook, Rezept 2.6, "Working with Roman numerals". Es ist schön, wenn eine Überzeugung bestätigt wird: Sakuro Ozawa, der Autor des Moduls Roman, hat das Problem deutlich eleganter gelöst. Aber zu meiner großen Freude ist seine Lösung zumindest bei der Umwandlung von Dezimalzahlen in römische Zahlen 72% langsamer als mein Skript (Benchmark: 10 Mio Umwandlungen von 1984). Ein Beleg dafür, dass Gewalt (in diesem Fall die brute force regex-Methode) manchmal doch eine Lösung ist. Umgekehrt (10 Mio Umwandlungen von MMDCXLIX) läuft es weniger gut: Mr. Ozawa lässt mich mit 86% schlechterer Performance ganz alt aussehen. So ist das Leben.
#!/usr/bin/perl -w $zahl = <>; if ($zahl =~ m/[MDCLXVI]/){ while ($zahl =~ m/I(?!(V|X))/g){ $arabsum += 1 } while ($zahl =~ m/I(?=(V|X))/g){ $arabsum -= 1 } while ($zahl =~ m/V/g){ $arabsum += 5 } while ($zahl =~ m/X(?!(L|C))/g){ $arabsum += 10 } while ($zahl =~ m/X(?=(L|C))/g){ $arabsum -= 10 } while ($zahl =~ m/L/g){ $arabsum += 50 } while ($zahl =~ m/C(?!(D|M))/g){ $arabsum += 100 } while ($zahl =~ m/C(?=(D|M))/g){ $arabsum -= 100 } while ($zahl =~ m/D/g){ $arabsum += 500 } while ($zahl =~ m/M/g){ $arabsum += 1000 } print $arabsum; } else { @romarray = split //, $zahl; $romlength = scalar @romarray; if ($romlength >= 7) { print "Maximal sechsstellige Zahlen!"; } else { if ($romlength == 6) { $romsum .= "M" x ($romarray[-6] * 100); } if ($romlength >= 5) { $romsum .= "M" x ($romarray[-5] * 10); } if ($romlength >= 4) { $romsum .= "M" x $romarray[-4]; } if ($romlength >= 3) { $romsum .= "C" x $romarray[-3]; } if ($romlength >= 2) { $romsum .= "X" x $romarray[-2]; } if ($romlength >= 1) { $romsum .= "I" x $romarray[-1]; } $romsum =~ s/C{9}/CM/g; $romsum =~ s/C{5}/D/g; $romsum =~ s/C{4}/CD/g; $romsum =~ s/X{9}/XC/g; $romsum =~ s/X{5}/L/g; $romsum =~ s/X{4}/XL/g; $romsum =~ s/I{9}/IX/g; $romsum =~ s/I{5}/V/g; $romsum =~ s/I{4}/IV/g; print $romsum;} }