Zahlen zu römische Zahlen wandeln...

Code-Stücke können hier veröffentlicht werden.
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Zahlen zu römische Zahlen wandeln...

Beitragvon jens » Donnerstag 4. Dezember 2008, 09:41

Letztens hätte ich es gebrauchen könne, nun hab ich es gefunden:

Code: Alles auswählen

def format_roman(case, counter):
    ones = ['i', 'x', 'c', 'm']
    fives = ['v', 'l', 'd']
    label, index = '', 0
    # This will die of IndexError when counter is too big
    while counter > 0:
        counter, x = divmod(counter, 10)
        if x == 9:
            label = ones[index] + ones[index+1] + label
        elif x == 4:
            label = ones[index] + fives[index] + label
        else:
            if x >= 5:
                s = fives[index]
                x = x-5
            else:
                s = ''
            s = s + ones[index]*x
            label = s + label
        index = index + 1
    if case == 'I':
        return label.upper()
    return label

for i in xrange(20):
    print format_roman("I", i)

Ausgabe:
I
II
III
IV
V
VI
VII
VIII
IX
X
XI
XII
XIII
XIV
XV
XVI
XVII
XVIII
XIX


Ist allerdings nicht von mir, sondern steckt in den Standard lib im formatter.AbstractFormatter ;) Hab es nur aus der Klasse herraus gelöst.

Ist nicht in der Doku erwähnt, siehe: http://docs.python.org/dev/library/form ... -formatter

Dumm finde ich das mit dem .upper() irgendwie komisch gemacht, statt True/False zu nehmen...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
DeJe
User
Beiträge: 39
Registriert: Sonntag 23. November 2008, 19:38

Beitragvon DeJe » Donnerstag 4. Dezember 2008, 10:47

Das finde ich auch unglücklich.
Mir gefällt auch die Reihenfolge der Parameter nicht.

Code: Alles auswählen

def format_roman(counter, upper_case=True):
    ...
    return label.upper() if upper_case else label
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Donnerstag 4. Dezember 2008, 10:50

Ja, das stimmt. Würde ich eigentlich auch so machen ;)

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Beitragvon rayo » Donnerstag 4. Dezember 2008, 11:23

Warum upper() überhaupt in der Funktion aufrufen? Ich finde das gehört absolut nicht in diese Funktion.

Falls das einer braucht kann er immernoch format_roman(zahl).upper() aufrufen.

Gruss
Benutzeravatar
SigMA
User
Beiträge: 181
Registriert: Sonntag 4. April 2004, 13:27
Wohnort: Freiburg
Kontaktdaten:

Beitragvon SigMA » Donnerstag 4. Dezember 2008, 18:57

Naja die römischen Zahlen sind nun mal nicht "iv" und "iii" sondern "IV" und "III"

Gruß
Leichtdio.de - Das Kreativ-Blog
http://www.leichtdio.de
DeJe
User
Beiträge: 39
Registriert: Sonntag 23. November 2008, 19:38

Beitragvon DeJe » Donnerstag 4. Dezember 2008, 19:07

So ist es.
Deshalb wäre (laufzeitoptimiert) folgende Variante wahrscheinlich sowieso sinnvoller:

Code: Alles auswählen

def format_roman(counter, upper_case=True):
    ones = ['I', 'X', 'C', 'M']
    fives = ['V', 'L', 'D']
    ...
    return label if upper_case else label.lower()

Naja, sooo viel macht das ja nicht aus. ;)
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Beitragvon sma » Samstag 6. Dezember 2008, 11:57

Nur echt wäre der Algorithmus ja, wenn er die Unicode-Symbole U+2160 bis U+2180 benutzen würde :) Python 3 kann die sogar auch mit upper() und lower() ineinander überführen, erkennt sie aber weder als Buchstaben noch als Ziffern. Komische Biester.

Auf dem Mac ist übrigens deren Kerning kaputt. Obwohl ich den nicht-proportionalen Font Monaco im Terminal benutze, laufen die Zeichen ineinander. Grummel.

Stefan
Benutzeravatar
roschi
User
Beiträge: 225
Registriert: Samstag 29. März 2008, 18:58
Wohnort: Thueringen, Deutschland
Kontaktdaten:

Beitragvon roschi » Montag 22. Dezember 2008, 20:47

hallo!

Code: Alles auswählen

# -*- coding: iso-8859-15 -*-

"""This module converts Roman numerals
into integers and also reversed.
The numbers must be in range 1...4999!

Methods:
 rtoi    - Roman number -> Integer
 itor    - Integer -> Roman number

Example:
>>> rtoi('XVI')
<<< 16
>>> itor(16)
<<< 'XVI'"""

import re

class OutOfRangeError(Exception): pass
class NotIntegerError(Exception): pass
class InvalidRomanNumeralError(Exception): pass

MAX_ROMAN_NUMERAL = 4999

RomanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500),
                   ('CD', 400), ('C', 100), ('XC', 90),
                   ('L', 50), ('XL', 40), ('X', 10),
                   ('IX', 9), ('V', 5), ('IV', 4),
                   ('I',  1))

ValidRomanNumeralPattern = re.compile( \
 """
 ^
 M{0,4}            # thousands - 0 to 4 M's
 (CM|CD|D?C{0,3})  # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
                   # or 500-800 (D, followed by 0 to 3 C's)
 (XC|XL|L?X{0,3})  # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
                   # or 50-80 (L, followed by 0 to 3 X's)
 (IX|IV|V?I{0,3})  # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
                   # or 5-8 (V, followed by 0 to 3 I's)
 $
 """, re.VERBOSE)

def itor(n):
  """itor(int) -> string
     Converts integers to Roman numbers"""

  if not (0 < n < 5000):
    raise OutOfRangeError, "number out of range (must be 1...%s)" \
                           % MAX_ROMAN_NUMERAL
  if int(n) <> n:
    raise NotIntegerError, "non-integers can not be converted"
  result = ""
  for num, i in RomanNumeralMap:
    while n >= i:
      result += num
      n -= i
  return result

def rtoi(s):
  """rtoi(string) -> int
     Converts Roman numbers to integers"""

  if not s:
    raise InvalidRomanNumeralError, "Input can not be blank"
  if not ValidRomanNumeralPattern.search(s):
    raise InvalidRomanNumeralError, "Invalid Roman numeral: '%s'" % s

  result = 0
  index = 0
  for num, i in RomanNumeralMap:
    while s[index:index+len(num)] == num:
      result += i
      index += len(num)
  return result


hab ich mir mal zusammengebastelt.
vorlage war ein beispiel aus 'dive into python'.

lg
roschi
Fuer Alle, die in Python einsteigen wollen, kann ich das Buch A Byte of Python nur waermstens empfehlen!
Nagila Hawa
User
Beiträge: 16
Registriert: Montag 9. Juni 2008, 18:20
Kontaktdaten:

Beitragvon Nagila Hawa » Sonntag 28. Dezember 2008, 19:27

Moin!

Beim Range Check fehlt die Konstante MAX_ROMAN_NUMERAL.

Ich finde das immer eine gute Übung. Ich bin auch gerade dabei (allerdings in Ada) einen eigenen Datentyp "Roman" zu schreiben, mit dem man dann ganz normal, wie mit jedem numerischen Datentyp rechnen kann (obwohl es technisch gesehen ein String ist).
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Sonntag 28. Dezember 2008, 21:54

Nagila Hawa hat geschrieben:Ich finde das immer eine gute Übung. Ich bin auch gerade dabei (allerdings in Ada) einen eigenen Datentyp "Roman" zu schreiben, mit dem man dann ganz normal, wie mit jedem numerischen Datentyp rechnen kann (obwohl es technisch gesehen ein String ist).

Stimmt, mit Python wäre so eine Übung ja zugegebenermaßen auch etwas zu trivial 8)
My god, it's full of CARs! | Leonidasvoice vs Modvoice
lunar

Beitragvon lunar » Sonntag 28. Dezember 2008, 23:11

Das gab es übrigens schon fertig: roman.py. DiveIntoPython-Lesern müsste das bekannt sein ...
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Beitragvon BlackVivi » Sonntag 28. Dezember 2008, 23:29

Leonidas hat geschrieben:
Nagila Hawa hat geschrieben:Ich finde das immer eine gute Übung. Ich bin auch gerade dabei (allerdings in Ada) einen eigenen Datentyp "Roman" zu schreiben, mit dem man dann ganz normal, wie mit jedem numerischen Datentyp rechnen kann (obwohl es technisch gesehen ein String ist).

Stimmt, mit Python wäre so eine Übung ja zugegebenermaßen auch etwas zu trivial 8)


http://paste.pocoo.org/show/97096/

Äußerst trivial, jop. Nicht perfekt, weit davon entfernt, aber einfach so ohne zu überlegen in nichmal 2 Minuten zusammenprogrammiert.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Beitragvon audax » Montag 29. Dezember 2008, 08:01

daher fehlt dir auch __radd__, etc....
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Beitragvon Darii » Montag 29. Dezember 2008, 14:14

sma hat geschrieben:Auf dem Mac ist übrigens deren Kerning kaputt. Obwohl ich den nicht-proportionalen Font Monaco im Terminal benutze, laufen die Zeichen ineinander. Grummel.
Laut Wikipedia sind sie nur zur Kompatibilität gedacht und nicht zur Benutzung in Schriften mit Horizontaler Schreibrichtung vorgesehen, vielleicht liegts daran? :)
Nagila Hawa
User
Beiträge: 16
Registriert: Montag 9. Juni 2008, 18:20
Kontaktdaten:

Beitragvon Nagila Hawa » Montag 29. Dezember 2008, 23:25

Wow, das ist ja wirklich winzig das Modul! Ich glaube ich muß mal öfter mit Python arbeiten, damit ich das überhaupt verstehe und Python wirklich ausnutzen kann (derzeit sehen Python-Programme bei mir meistens recht konservativ aus...). :D

Dazu fällt mir dann aber eine eher allgemeine Frage ein: Ich komme nicht wirklich hinter das Typensystem von Python, oder allgemein dynamisch typisierten Sprachen. Inwiefern ist bei so einem Konstrukt denn eigentlich Typsicherheit gewährt? Wie funktioniert das, was macht der Interpreter? Gibt es irgendwo vielleicht eine Art Doku speziell über Typisierung und erstellen eigener Typen in Python? In Tutorials ist das meistens recht kurz gefasst. Das Typsystem in Ada ist ja auch recht mächtig und eigen, aber das lernt man da von der Pike an und ist daher in Tutorials recht genau erläutert (ohne dem lässt sich auch schlecht arbeiten...), in Python habe ich mich noch nicht so damit auseinandergesetzt.

Vielleicht bin ich auch einfach von der strikten Struktutr streng typisierter Sprachen wie Ada oder von gefährlichen Typ-Mißbrauch-Sprachen wie C zu sehr beeinflußt worden, um Python jemals richtig zu lernen. :(

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder