Freitag, 11. Januar 2013

Römische Zahlen

Ein Skript soll römische Zahlen umrechnen und zurück.

Zunächst die Funktion, die eine Ganzzahl in eine römische Zahl konvertiert:
def int_to_roman(n):
    ''' Soll eine natuerliche Zahl > 0 und kleiner 4000
    erhalten und dafuer die roemische Zahl ausgeben.

    '''
    roman_numerals = []
    
    zahlen = {1000: "M",
              900: "CM",
              500: "D",
              400: "CD",
              100: "C",
              90: "XC",
              50: "L",
              40: "XL",
              10: "X",
              9: "IX",
              5: "V",
              4: "IV",
              1: "I"}

    if n > 0 and n < 4000 and type(n) == int:
        for zahl in sorted(zahlen.keys(),reverse=True):
            roman_numerals.append(n // zahl * zahlen[zahl])
            n = n % zahl

        return "".join(roman_numerals)


for i in [1984,534,923,12,18,1,2,23,456,234,872,3999]:
    print(i,int_to_roman(i),sep="\t")
Die Funktion, die eine natürliche Zahl in eine römische Zahl konvertiert, war recht einfach zu implementieren. Der Algorithmus funktioniert wie folgt: Für jeden Schlüssel im Wörterbuch "zahlen" führe folgendes aus: Dividiere die gegebene Zahl n durch die Zahl und füge nun der Liste das entsprechende römische Zahlzeichen entsprechend der Anzahl hinzu. Die Zahl n sei der Rest der Division von n durch die Zahl. Gib am Ende die römische Zahl zurück.

Die Funktion, die aus einer römischen Zahl eine natürliche Zahl macht, gefällt mir noch nicht, auch wenn das Skript funktioniert. Ich empfinde die Variante mit zwei Listen als unelegant:
def roman_to_int(roemische_zahl):
    ''' Soll eine roemische Zahl erhalten und
    dafuer die ganze Zahl ausgeben.

    '''

    zahlen = {"M": 1000,
              "D":  500,
              "C":  100,
              "L":   50,
              "X":   10, 
              "V":    5,
              "I":    1}
    
    liste = []
    
    for i,a in enumerate(roemische_zahl):
        if i == len(roemische_zahl) - 1:
            liste.append(zahlen[a])
        elif zahlen[a] < zahlen[roemische_zahl[i+1]]:
            liste.append(-1 * zahlen[a])
        else:
            liste.append(zahlen[a])
    
    return sum(liste)


for i in ["XXIII","CMXXIII","MCMLXXXIV","MMMCMXCIX"]:
    print(i,roman_to_int(i),sep="\t")
Alternative Lösungen bietet u. a. das Internet, d. h. auch, dass mein Skript wahrscheinlicher noch besser formuliert werden kann. Ganz spannend finde ich die Lösung von Tim Valenta hier bei ActiveState. Wenn ich es richtig sehe, dann vereinfacht er über map() das Vorhalten der Schlüssel und muss nicht - wie bei meiner obigen Lösung - zwei Wörterbücher einbauen. Seine Lösung für die Umrechnung von Ganzzahlen in römische Zahlen entspricht ziemlich gut meinem Ansatz. Der andere Ansatz ist deutlich knapper formuliert.

Keine Kommentare:

Kommentar veröffentlichen