Donnerstag, 10. März 2011

 

Lösungen zu "Übungsbeispiele zu Sequenzen, Schleifen und Funktionen in Python" (POS1: 1B)

Hier mögliche Lösungen zu der Aufgabe "Übungsbeispiele zu Sequenzen, Schleifen und Funktionen in Python (POS1: 1B)". Einige der Aufgaben enthalten Suchaufgaben. Die Funktionen dazu sind teilweise nicht "strukturiert" programmiert, das heißt, dass sie in diesen Fällen nicht nur ein return sondern mehrere Ausgänge haben. Um das zu verdeutlichen, beachten Sie folgendes Beispiel:
def isint(string):
    """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, 
    nur Ziffern).
    Prüfe nur Ziffernbereich."""
    if len(string) > 0:
        if string[0] == '+' or string[0] == '-':
            for c in string[1:]:
                if c < '0' or c > '9':
                    return False
        else:
            for c in string:
                if c < '0' or c > '9':
                    return False
    else:
        return False
    return True
Hier erfolgt ein return False aus den Schleifen über den String string, sobald ein Fehler gefunden wurde. Das vereinfacht den Algorithmus, widerspricht aber der strukturierten Programmierung, die bei Funkionen nur einen Ausgang erlaubt (bei Schleifen gilt das auch, die Schleife verlässt man nur durch die Schleifenbedingung, nicht durch break oder eben return). Beim Debuggen größerer Systeme ist es von Vorteil, wenn man sich darauf verlassen kann, dass jede Funktion nur einen Ausgang hat, denn man braucht dann nur diesen einen beobachten und nicht mehrere.
Bei obigem Beispiel müsste man while-Schleifen verwenden:
def isint(string):
    """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, 
    nur Ziffern).
    Prüfe nur Ziffernbereich."""
    ok = True
    if len(string) > 0:
        if string[0] == '+' or string[0] == '-':
            i = 1
            while ok and i < len(string):
                if string[i] < '0' or string[i] > '9':
                    ok = False
                i += 1
        else:
            i = 0
            while ok and i < len(string):
                if string[i] < '0' or string[i] > '9':
                    ok = False
                i += 1
    else:
        ok = False
    return ok
Diese Variante könne man noch "vereinfachen", weil sich die beiden Zweige mit oder ohne Vorzeichen nur im Startwert der Laufvariable i unterscheiden:
def isint(string):
    """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, 
    nur Ziffern).
    Prüfe nur Ziffernbereich."""
    ok = True
    if len(string) > 0:
        if string[0] == '+' or string[0] == '-':
            i = 1
        else:
            i = 0
        while ok and i < len(string):
            if string[i] < '0' or string[i] > '9':
                ok = False
            i += 1
    else:
        ok = False
    return ok
Die "nicht strukturierte" Variante ist aber bei weitem schneller entwickelt und durch die automatischen Tests ist auch sichergestellt, dass sie funktioniert.

Die Tests verwenden assert(), um die Ergebnisse mit den erwarteten Ergebnissen zu vergleichen. assert() bricht das Programm auf der Stelle ab, wenn die Bedingung nicht erfüllt ist. Dadurch hat man die Möglichkeit, den Fehler einzugrenzen. Passt die Bedingung, so läuft das Programm einfach weiter.

"""
author: Haberstroh, Harald
matnr:  d09666
file:   sequenzenbeispiele.py
desc:   Beispiele einfacher Funktionen mit Sequenzen (vgl. Programmierblog)
        Einige Funktionen bauen auf den anderen auf.
        
        Zu jeder Funktion (ausgenommen Hilfsfunktion) gibt es eine Testfunktion
        die die jeweilige Funktion mit Testwerten prüft.
        
        Die Funktion assert() prüft den Wahrheitswert des Parameters. Ist dieser
        True, so läuft das Programm einfach weiter. Ist er jedoch False, wird
        das Programm mit einer Fehlermeldung und Zeilennummer abgebrochen.
        Man kann dadurch feststellen, welcher Test nicht funktioniert hat.
date:   7.3.2011
class:  Lehrer
catnr:  33
"""
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def isint(string):
    """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, 
    nur Ziffern).
    Prüfe nur Ziffernbereich."""
    if len(string) > 0:
        if string[0] == '+' or string[0] == '-':
            for c in string[1:]:
                if c < '0' or c > '9':
                    return False
        else:
            for c in string:
                if c < '0' or c > '9':
                    return False
    else:
        return False
    return True

def test_isint():
    assert(isint("") == False)
    assert(isint("a") == False)
    assert(isint("1a") == False)
    assert(isint("a1") == False)
    assert(isint("1+1") == False)
    assert(isint("1+") == False)
    assert(isint("1") == True)
    assert(isint("+1") == True)
    assert(isint("-1") == True)
    assert(isint("11212") == True)
    assert(isint("-11212") == True)
    assert(isint("+11212") == True)
    print("test_isint() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def isintb(string, basis):
    """prüft, ob der String eine ganze Zahl zur Basis basis ist (Vorzeichen
    optional, nur Ziffern).
    Baue String mit gültigen Zeichen zusammen und prüfe dann, ob jedes
    Zeichen in diesem String vorkommt."""
    if basis > 1:
        gueltig = "" # "Liste" der gültigen Zeichen für geg. Basis
        if basis > 10: # Ziffern und Buchstaben (immer groß und klein)
            for z in range(10):
                gueltig += chr(z + ord('0'))
            for z in range(basis - 10):
                gueltig += chr(z + ord('a')) # Kleinbuchstabe
                gueltig += chr(z + ord('A')) # Großbuchstabe
        else: # nur Ziffern
            for z in range(basis):
                gueltig += chr(z + ord('0'))
        if len(string) > 0:
            if string[0] == '+' or string[0] == '-': # Vorzeichen
                for c in string[1:]:
                    if c not in gueltig:
                        return False
            else:
                for c in string:
                    if c not in gueltig:
                        return False
        else:
            return False
    else:
        return False
    return True # alles OK

def test_isintb():
    assert(isintb("", 2) == False)
    assert(isintb("a", 2) == False)
    assert(isintb("1a", 2) == False)
    assert(isintb("a1", 2) == False)
    assert(isintb("1+1", 2) == False)
    assert(isintb("1+", 2) == False)
    assert(isintb("1", 2) == True)
    assert(isintb("+1", 2) == True)
    assert(isintb("-1", 2) == True)
    assert(isintb("11212", 2) == False)
    assert(isintb("-11212", 2) == False)
    assert(isintb("+11212", 2) == False)
    assert(isintb("11212", 3) == True)
    assert(isintb("-11212", 3) == True)
    assert(isintb("+11212", 3) == True)
    assert(isintb("aBCdeF", 16) == True)
    assert(isintb("-aBCdeF", 16) == True)
    assert(isintb("+aBCdeF", 16) == True)
    print("test_isintb() ok")
    
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----

def sumdigits(zahl):
    """Berechnet die Ziffernsumme aus der gegebenen Zahl (int)"""
    sum = 0
    while zahl != 0:
        sum += zahl % 10 # Rest ist immer Einerstelle
        zahl = zahl // 10
    return sum

def test_sumdigits():
    assert(sumdigits(0) == 0)
    assert(sumdigits(1) == 1)
    assert(sumdigits(7) == 7)
    assert(sumdigits(10) == 1)
    assert(sumdigits(11) == 2)
    assert(sumdigits(123) == 6)
    assert(sumdigits(1010) == 2)
    print("test_sumdigits() ok")
    
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def wert_der_ziffer(ziffer):
    """liefert den Wert der Ziffer ziffer (0..9, bzw. A, B, C, ...)"""
    if ord(ziffer) <= ord("9"):
        wert = ord(ziffer) - ord("0")
    else:
        wert = ord(ziffer) - ord("A") + 10
    return wert

def horner(zahl, basis):
    """berechnet Dezimalzahl aus zahl (String) zur Basis basis.
    liefert Zahl. Hornerschema!"""
    dez = 0
    for ziffer in zahl:
        dez *= basis
        dez += wert_der_ziffer(ziffer)
    return dez

def test_horner():
    assert(horner("", 10) == 0)
    assert(horner("1", 10) == 1)
    assert(horner("12", 10) == 12)
    assert(horner("123", 10) == 123)
    assert(horner("1", 2) == 1)
    assert(horner("10", 2) == 2)
    assert(horner("11", 2) == 3)
    assert(horner("4", 16) == 4)
    assert(horner("A", 16) == 10)
    assert(horner("10", 16) == 16)
    print("test_horner() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def isipv4(string):
    """Prüft, ob der gegebene String eine IPv4-Adresse enthält.
    IPv4-Adressen sind 4 Zahlen zwischen 0 und 255, die durch einen
    Punkt getrennt sind.
    Beispiele: 127.0.0.1, 193.170.149.129, 81.200.64.185
    Ungültige: 81.2010.64.185, 123.23.12, 127,0,0,1"""
    zahl = ""
    anzpunkte = 0
    anzziffer = 0
    for z in string:
        if '0' <= z <= '9': 
            zahl += z
            anzziffer += 1
        elif z == '.' and anzziffer > 0: # mindestens 1 Ziffer vor Zahl
            if not (0 <= horner(zahl, 10) <= 255):
                return False
            zahl = "" # neu beginnen
            anzziffer = 0
            anzpunkte += 1
        else:
            return False
    if anzpunkte == 3 and anzziffer > 0: # nach 3. Punkt eine Zahl!
        if not (0 <= horner(zahl, 10) <= 255):
            return False
        return True
    else:
        return False

def test_isipv4():
    assert(isipv4("127.0.0.1"))
    assert(isipv4("193.170.149.129"))
    assert(isipv4("81.200.64.185"))
    assert(not isipv4(""))
    assert(not isipv4("81.2010.64.185"))
    assert(not isipv4("123.23.12"))
    assert(not isipv4("123.23.12."))
    assert(not isipv4("123.23.12.3.3"))
    assert(not isipv4("123.23.12.3."))
    assert(not isipv4("127,0,0,1"))
    print("test_isipv4() ok")
    
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def anz_zahlen(string):
    """ermittelt die Anzahl der ganzen Zahlen im String"""
    anzahl = 0
    in_zahl = False
    for zeichen in string:
        if zeichen in "0123456789":
            if not in_zahl:
                anzahl += 1
                in_zahl = True
        else:
            in_zahl = False
    return anzahl

def test_anz_zahlen():
    string = "das ist eine Zahl 123 und noch eine 1 und noch eine 3213x23123"
    assert(4 == anz_zahlen(string))
    assert(0 == anz_zahlen("keine"))
    assert(1 == anz_zahlen("eine Zahl 123"))
    assert(2 == anz_zahlen("zwei 23 und 324"))
    assert(3 == anz_zahlen("drei 23 34 22"))
    assert(4 == anz_zahlen("vier 234 234 234 45"))
    assert(5 == anz_zahlen("5 234 234 234 45"))
    print("test_anz_zahlen() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def sum_zahlen(string):
    """ermittelt die Summe der ganzen Zahlen im String. Eine Zahl
    ist eine ununterbrochene Folge von Ziffern.
    Beispiel: sum_zahlen("x 34 3 12k33 44 hallo 23") liefert 149"""
    summe = 0
    zahl = ""
    for zeichen in string:
        if zeichen in "0123456789":
            zahl += zeichen
        else:
            summe += horner(zahl, 10) # umrechnen und dazuzählen
            zahl = "" # neu beginnen
    if len(zahl) > 0: # zuletzt war Zahl, daher dazurechnen
        summe += horner(zahl, 10)
    return summe

def test_sum_zahlen():
    string = "das ist eine Zahl 123 und noch eine 1 und noch eine 3213x23123"
    assert(26460 == sum_zahlen(string))
    assert(0 == sum_zahlen("keine"))
    assert(123 == sum_zahlen("eine Zahl 123"))
    assert(347 == sum_zahlen("zwei 23 und 324"))
    assert(79 == sum_zahlen("drei 23 34 22"))
    assert(747 == sum_zahlen("vier 234 234 234 45"))
    assert(752 == sum_zahlen("5 234 234 234 45"))
    print("test_sum_zahlen() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def iskonto(string):
    """Prüft, ob der String eine gültige Kontonummer enthält. Dabei
    gelten folgende Regeln:
    1. genau 9 Ziffern (es dürfen Leerzeichen dazwischen sein
    2. die letzte Ziffer ist eine Prüfziffer und es gilt
       Die Kontonummer ist genau 9 Stellen lang und ist dann richtig, 
       wenn die folgendermaßen gebildete Summe auf Null endet:
       Ziffern mit ungeradem Index werden addiert(=Teilsumme1);
       Ziffern mit geradem Index werden verdoppelt und das jeweilige 
       Produkt addiert, wenn es einstellig ist, andernfalls wird die
       Quersumme des Produkts addiert(=Teilsumme2);
       Summe= teilsumme1 + Teilsumme2
    Beispiel:
       123456782 1+    3+    5+      7+     2  = 18 Teilsumme1
                   2*2+  4*2+  (1+2)+  (1+6)   = 22 Teilsumme2
                               6*2=12  8*2=16
                                               ------
                                                 40 Summe mod 10= Null
    Beispiele für Kontonummern:
       697199107 richtige Kontonummer
       723016689 richtige Kontonummer
       723016699 falsche Kontonummer
    """
    # entferne alle Leerzeichen (sind ja erlaubt)
    kontonummer = ""
    for c in string:
        if '0' <= c <= '9':
            kontonummer += c
        elif c != ' ':
            return False # nur Ziffern und Leerzeichen erlaubt!
    if len(kontonummer) != 9:
        return False
    
    summe = 0 # alles in einer Summe, aufteilen ist nicht nötig
    for i in range(len(kontonummer)):
        ziffer = ord(kontonummer[i]) - ord('0')
        if (1 + i) % 2 == 1: # ungerade
            summe += ziffer
        else: # gerade
            doppelt = ziffer * 2
            if doppelt >= 10: # Zwei Ziffern
                summe += doppelt % 10 # Einer
                summe += doppelt // 10 # Zehner
            else: # immer noch eine Ziffer
                summe += doppelt
    return summe % 10 == 0 # Summe muss durch 10 teilbar sein

def test_iskonto():
    assert(not iskonto(""))
    assert(not iskonto("a"))
    assert(not iskonto("69719a9107"))
    assert(not iskonto("69719917"))
    assert(not iskonto("723016699"))
    assert(iskonto("723016689"))
    assert(iskonto("697199107"))
    assert(iskonto("123456782"))
    assert(iskonto("12 345 6782"))
    print("test_iskonto() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def reverse_s(string):
    """liefert String in umgekehrter Reihenfolge zurück"""
    s = ""
    for c in string:
        s = c + s
    return s

def test_reverse_s():
    assert("" == reverse_s(""))
    assert("a" == reverse_s("a"))
    assert("ba" == reverse_s("ab"))
    assert("abc" == reverse_s("cba"))
    print("test_reverse() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def toupper(string):
    """liefert String in Großbuchstaben zurück"""
    s = ""
    for c in string:
        if 'a' <= c <= 'z':
            s += chr(ord(c) - ord('a') + ord('A'))
        elif c == 'ä':
            s += 'Ä'
        elif c == 'ö':
            s += 'Ö'
        elif c == 'ü':
            s += 'Ü'
        else:
            s += c
    return s

def test_toupper():
    assert("" == toupper(""))
    assert("A" == toupper("a"))
    assert("AB" == toupper("ab"))
    assert("ÄBC" == toupper("äbc"))
    assert("A" == toupper("a"))
    assert("AB" == toupper("Ab"))
    assert("ÄBC" == toupper("äBc"))
    print("test_toupper() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def tolower(string):
    """liefert String in Kleinbuchstaben zurück"""
    pass
    s = ""
    for c in string:
        if 'A' <= c <= 'Z':
            s += chr(ord(c) - ord('A') + ord('a'))
        elif c == 'Ä':
            s += 'ä'
        elif c == 'Ö':
            s += 'ö'
        elif c == 'Ü':
            s += 'ü'
        else:
            s += c
    return s

def test_tolower():
    assert("" == tolower(""))
    assert("a" == tolower("A"))
    assert("ab" == tolower("AB"))
    assert("äbc" == tolower("ÄBC"))
    assert("a" == tolower("A"))
    assert("ab" == tolower("Ab"))
    assert("äbc" == tolower("äBc"))
    print("test_tolower() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def isupper(string):
    """prüft, ob String nur Großbuchstaben enthält"""
    for c in string:
        if 'a' <= c <= 'z' or c in "äöü": # ein Kleinbuchstabe
            return False
    return True

def test_isupper():
    assert(isupper(""))
    assert(isupper("A"))
    assert(isupper("AEÄÖ"))
    assert(not isupper("a"))
    assert(not isupper("abcö"))
    assert(not isupper("AbC"))
    print("test_isupper() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def islower(string):
    """prüft, ob String nur Kleinbuchstaben enthält"""
    for c in string:
        if 'A' <= c <= 'Z' or c in "ÄÖÜ": # ein Großbuchstab
            return False
    return True

def test_islower():
    assert(islower(""))
    assert(islower("a"))
    assert(islower("aeöä"))
    assert(not islower("A"))
    assert(not islower("ABCÖ"))
    assert(not islower("AbC"))
    print("test_islower() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def ispalindrom(string):
    """Prüft, ob der String ein Palindrom ist (von vorne und hinten
    gelesen gleich)."""
    for i in range(len(string)):
        if string[i] != string[-1 - i]:
            return False
    return True

def test_ispalindrom():
    assert(ispalindrom(""))
    assert(ispalindrom("a"))
    assert(ispalindrom("aa"))
    assert(ispalindrom("aba"))
    assert(ispalindrom("abba"))
    assert(not ispalindrom("ab"))
    assert(not ispalindrom("abb"))
    assert(not ispalindrom("abab"))
    print("test_ispalindrom() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def ispalindrom_l(liste):
    """Prüft, ob die Liste von vorne und hinten gelesen gleich ist."""
    return ispalindrom(liste) # sollte äquivalent sein!

def test_ispalindrom_l():
    assert(ispalindrom_l([]))
    assert(ispalindrom_l([1]))
    assert(ispalindrom_l([1, 1]))
    assert(ispalindrom_l([1, 2, 1]))
    assert(ispalindrom_l([1, 2, 2, 1]))
    assert(not ispalindrom_l([1, 2]))
    assert(not ispalindrom_l([1, 2, 2]))
    assert(not ispalindrom_l([1, 2, 1, 2]))
    print("test_ispalindrom_l() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def reverse_l(liste):
    """liefert die Liste in umgekehrter Reihenfolge zurück"""
    l = []
    for e in liste:
        l = [e] + l
    return l

def test_reverse_l():
    assert([] == reverse_l([]))
    assert([1] == reverse_l([1]))
    assert([1, 2] == reverse_l([2, 1]))
    assert([1, 2, 3] == reverse_l([3, 2, 1]))
    print("test_reverse_l() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def sum(liste):
    """liefert die Summe aller Zahlen in der Liste"""
    summe = 0
    for e in liste:
        summe += e
    return summe

def test_sum():
    assert(0 == sum([]))
    assert(12 == sum([12]))
    assert(12 == sum([4, 8]))
    assert(12 == sum([4, 4, 4]))
    print("test_sum() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def mittelwert(liste):
    """liefert den Mittelwert (Durchschnitt) aller Zahlen in der Liste"""
    if len(liste) > 0:
        return sum(liste) / len(liste)
    else:
        return 0

def test_mittelwert():
    assert(0 == mittelwert([]))
    assert(1 == mittelwert([1]))
    assert(1.5 == mittelwert([1, 2]))
    assert(2 == mittelwert([2, 2, 2]))
    assert(2 == mittelwert([1, 2, 3]))    
    print("test_mittelwert() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def rmdups(liste):
    """(ReMove DUPlicates) liefert Liste, aus der alle Vielfachen entfernt
    (hintereinander).
    Beispiele: [1, 2, 2, 2, 5, 2, 3, 2, 2, 23] -> [1, 2, 5, 2, 3, 2, 23]
               [99, 99, 23, 99, 99, 12, 2] -> [99, 23, 99, 12, 2]
               [] -> []
               [1, 2, 4, 10] -> [1, 2, 4, 10]"""
    if len(liste) > 0:
        ret = [liste[0]]
        for e in liste:
            if ret[-1] != e: # letztes Element ungleich?
                ret.append(e)
        return ret
    else:
        return liste

def test_rmdups():
    assert([1, 2, 5, 2, 3, 2, 23] == rmdups([1, 2, 2, 2, 5, 2, 3, 2, 2, 23]))
    assert([99, 23, 99, 12, 2] == rmdups([99, 99, 23, 99, 99, 12, 2]))
    assert([] == rmdups([]))
    assert([1, 2, 4, 10] == rmdups([1, 2, 4, 10]))
    print("test_rmdups() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def isin(item, liste):
    """ist item in liste enthalten?"""
    for e in liste:
        if item == e:
            return True
    return False

def rmalldups(liste):
    """(ReMove ALL DUPlicates) liefert Liste, aus der alle Vielfachen
    entfernt (müssen nicht hintereinander stehen).
    Beispiele: [1, 2, 2, 2, 5, 2, 3, 2, 2, 23] -> [1, 2, 5, 3, 23]
               [99, 99, 23, 99, 99, 12, 2] -> [99, 23, 12, 2]
               [] -> []
               [1, 2, 4, 10] -> [1, 2, 4, 10]"""
    if len(liste) > 0:
        ret = [liste[0]]
        for e in liste:
#            if e not in ret: # schon vorhanden?
            if not isin(e, ret):
                ret.append(e)
        return ret
    else:
        return liste

def test_rmalldups():
    assert([] == rmalldups([]))
    assert([1, 2, 5, 3, 23] == rmalldups([1, 2, 2, 2, 5, 2, 3, 2, 2, 23]))
    assert([99, 23, 12, 2] == rmalldups([99, 99, 23, 99, 99, 12, 2]))
    assert([1, 2, 4, 10] == rmalldups([1, 2, 4, 10]))
    print("test_rmalldups() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def binsearch(liste, such):
    """liefert den Index von such in der sortierten Liste liste oder -1,
    wenn such in liste nicht vorkommt. Es ist die binäre Suche anzuwenden!
    """
    first = 0
    last = len(liste) - 1
    mid = (last - first) // 2 + first
    #print(first, mid, last)
    while len(liste) > 0 and first <= last:
        if such < liste[mid]:
            last =  mid - 1
        elif such > liste[mid]:
            first = mid + 1
        else:
            return mid #index found
        mid = (last - first) // 2 + first
        #print(first, mid, last)
    return -1 # not found

def test_binsearch():
    """static tests"""
    assert(binsearch([], 1) == -1)
    assert(binsearch([1], 2) == -1)
    assert(binsearch([1], 0) == -1)
    assert(binsearch([1], 1) == 0)
    assert(binsearch([1,3], 0) == -1)
    assert(binsearch([1,3], 2) == -1)
    assert(binsearch([1,3], 1) == 0)
    assert(binsearch([1,3], 3) == 1)
    assert(binsearch([1,3], 4) == -1)
    assert(binsearch([1,3,5], 2) == -1)
    assert(binsearch([1,3,5], 4) == -1)
    assert(binsearch([1,3,5], 1) == 0)
    assert(binsearch([1,3,5], 3) == 1)
    assert(binsearch([1,3,5], 5) == 2)
    assert(binsearch([1,3,5], 6) == -1)
    assert(binsearch([1,3,5,7], 0) == -1)
    assert(binsearch([1,3,5,7], 1) == 0)
    assert(binsearch([1,3,5,7], 3) == 1)
    assert(binsearch([1,3,5,7], 5) == 2)
    assert(binsearch([1,3,5,7], 7) == 3)
    assert(binsearch([1,3,5,7], 9) == -1)
    assert(binsearch([1,3,5,7], 2) == -1)
    assert(binsearch([1,3,5,7], 4) == -1)
    assert(binsearch([1,3,5,7], 6) == -1)
    import random
    for i in range(25):
        liste = [random.randint(0, 100) for i in range(100)]
        liste.sort()
        num = random.randint(0, 100)
        if num in liste:
            if binsearch(liste, num) < 0:
                print(liste)
                print("%d should be found in list" % num)
                assert(binsearch(liste, num) >= 0)
        else:
            if binsearch(liste, num) >= 0:
                print(liste)
                print("%d should not be found in list" % num)
                assert(binsearch(liste, num) < 0)
    print("test_binsearch() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def sumteilbar(liste, teiler):
    """Berechnet die Summe aller durch teiler teilbaren Zahlen der Liste"""
    summe = 0
    for e in liste:
        if e % teiler == 0:
            summe += e
    return summe

def test_sumteilbar():
    assert(0 == sumteilbar([], 2))
    assert(0 == sumteilbar([1], 2))
    assert(0 == sumteilbar([1, 3], 2))
    assert(0 == sumteilbar([1, 3, 23], 2))
    assert(2 == sumteilbar([2], 2))
    assert(2 == sumteilbar([1, 2], 2))
    assert(2 == sumteilbar([1, 2, 23], 2))
    assert(32 == sumteilbar([1, 8, 24], 2))
    assert(27 == sumteilbar([3, 8, 24], 3))
    print("test_sumteilbar() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def issorted(liste):
    """Prüft, ob die Liste sortiert ist, d.h. ob e1 <= e2 <= e3 <= ... <= en
    e1, e2, ... en sind die n Elemente der Liste mit Länge n"""
    for i in range(len(liste) - 1):
        if liste[i] > liste[i + 1]:
            return False
    return True

def test_issorted():
    assert(issorted([]))
    assert(issorted([1]))
    assert(issorted([1, 1]))
    assert(issorted([1, 3, 3, 4]))
    assert(not issorted([1, 0]))
    assert(not issorted([1, 2, 1]))
    print("test_issorted() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def printlxl(liste1, liste2):
    """gibt eine Multiplikationstabelle der beiden Listen aus.
    Zum Beispiel:
       a = [1, 2, 4, 5]
       b = [3, 2, 2]
       printlxl(a, b) gibt dann folgendes aus:
         3   2   2 
         6   4   4 
        12   8   8 
        15  10  10 
    Die erste Liste bestimmt die Anzahl der Zeilen, die zweite die Anzahl 
    der Spalten. Es wird immer ein Element der ersten Liste mit einem der
    zweiten Liste multipliziert.
    """
    erg = lxl(liste1, liste2)
    for zeile in erg:
        for spalte in zeile:
            print("%4d" % spalte, end = "")
        print()

def test_printlxl():
    a = [1, 2, 4, 5]
    b = [3, 2, 2]
    printlxl(a, b)
    print("test_printlxl() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def lxl(liste1, liste2):
    """liefert eine Multiplikationstabelle der beiden Listen (Liste von 
    Listen).
    Zum Beispiel:
       a = [1, 2, 4, 5]
       b = [3, 2, 2]
       lxl(a, b) liefert folgende Liste zurück:
       [[3, 2, 2], [6, 4, 4], [12, 8, 8], [15, 10, 10]]
       übersichtlich formatiert:
       [[3, 2, 2], 
        [6, 4, 4], 
        [12, 8, 8], 
        [15, 10, 10]]
    Die erste Liste bestimmt die Anzahl der "Zeilen", die zweite die Anzahl 
    der "Spalten". Es wird immer ein Element der ersten Liste mit einem der
    zweiten Liste multipliziert.
    """
    erg = []
    if len(liste2) > 0:
        for a in liste1:
            zeile = []
            for b in liste2:
                zeile.append(a * b)
            erg.append(zeile)
    return erg

def test_1x1():
    a = [1, 2, 4, 5]
    b = [3, 2, 2]
    assert([[3, 2, 2], [6, 4, 4], [12, 8, 8], [15, 10, 10]] == lxl(a, b))
    assert([] == lxl([], []))
    assert([] == lxl([], [1, 2]))
    assert([] == lxl([1, 2], []))
    print("test_1x1() ok")

#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
# Testaufrufe:
test_isint()
test_isintb()
test_sumdigits()
test_horner()
test_isipv4()
test_anz_zahlen()
test_sum_zahlen()
test_iskonto()
test_reverse_s()
test_toupper()
test_tolower()
test_isupper()
test_islower()
test_ispalindrom()
test_ispalindrom_l()
test_reverse_l()
test_sum()
test_mittelwert()
test_rmdups()
test_rmalldups()
test_binsearch()
test_sumteilbar()
test_issorted()
test_printlxl()
test_1x1()

Die Funktionen isupper() und islower() sind eigentlich nicht korrekt, denn liefert z.B. isupper("A4C") True. Man müsste also eher schreiben:

def isupper(string):
    """prüft, ob String nur Großbuchstaben enthält"""
    for c in string:
        if not ('A' <= c <= 'Z' or c in "ÄÖÜ"):
            return False
    return True

Labels: , ,


Kommentare:

Kommentar veröffentlichen

Abonnieren Kommentare zum Post [Atom]





<< Startseite

This page is powered by Blogger. Isn't yours?

Abonnieren Posts [Atom]