Aus dem OpenClipart-Project |
Problembeschreibung
Auf einer texanischen Rinderfarm soll für die Seriennummer einer Kuh eine Liste weiblicher Vornamen vorgeschlagen werden, wobei die Übersetzung sich am Tastenfeld eines Telefons orientiert, d. h. für die Zahl 2 kann im Vornamen der Buchstabe A, B oder C stehen.Ich verwende meine Telefontastatur, wie ich sie auf meinem Telefon vorfinde.
1 | 2 ABC |
3 DEF |
4 GHI |
5 JKL |
6 MNO |
7 PQRS |
8 TUV |
9 WXYZ |
Diese Änderung sollte unproblematisch sein. Die richtige Funktionsweise meines Programms kann später über die Tastatur überprüft werden. Wirft mir das Programm für den Code 23353 z. B. den Vornamen Adele aus, dann kann ich prüfen, ob die Buchstaben jeweils in den den Zahlen zugeordneten Buchstabenlisten enthalten sind.
Folglich stellt sich folgendes Problem: Schreibe ein Programm das für die Nummer eines Rinds alle validen Namen ausgibt, die für diese Nummer generiert werden können. Sonst lautet die Ausgabe „No matching names found“. Seriennummern dürfen maximal 9 Zahlen lang sein. Das Programm endet, wenn eine 0 eingegeben wird.
Vorüberlegungen
Die Aufgabenstellung führt zu folgenden Vorüberlegungen:
- Die Seriennummer eines Rindes darf keine 0 oder 1 enthalten, weil ich diesen Ziffern keinen Buchstaben zuweisen kann.
Die Verwendung des RE-Moduls bietet sich m. E. an. Die dynamische Generierung eines RE-Ausdrucks ist m. E. erforderlich.(Ging einfacher)
- Möglicherweise macht es Sinn die Vornamen in Listen entsprechend der Länge aufzuteilen. Das könnte helfen die Performanz zu verbessern.
Datendatei aufbauen
Ich habe mir - leider manuell - aus der Wikipedia eine Liste mit - laut Wikipedia - 1.761 weiblichen Vornamen (Stand März 2013) geholt und aufbereitet. Aus dieser Liste soll das Programm geeignete Namen auswählen.Die Vornamensliste wird aus dem Quelltext der Kategorienseiten heraus aufgebaut:
with open("Männlicher Vorname.txt") as f, open("Männliche Vornamen.txt","w") as g: for line in f: line = line.replace("\n","") # title="Zsuzsanna" if "title" in line: line = line.split('title="')[1] vorname = line.split('"')[0] vorname = vorname.replace(" (Vorname)","") vorname = vorname.replace(" (Name)","") print(vorname) vorname += "\n" g.write(vorname)Das war gerade etwas Handarbeit, aber noch im Rahmen und einfacher und schneller als sich beim Pywikipediabot einzulesen.
Die entsprechende Übersicht mit denn männlichen Vornamen bietet - laut Wikipedia - 3.390 männliche Vornamen (Stand März 2013).
Quelle: Deutschsprachige Wikipedia (2. März 2013)
Aus beiden Listen kann man die benötigte Vornamensliste aufbauen.
Ein- und Ausgabe
Die Eingabe stellt man sich bei HP in etwa in folgender Form vor:
Program Input 232 252473 727225 0 Program Output Possible names for #232 are: Ada Possible names for #252473 are: Blaise, Claire Possible names for #727225 are: PascalSieht leistbar aus.
Mein Programm
Das re-Modul kommt hier nicht zum Einsatz, weil es Treffer für Strings findet, nicht aber in Listen. Eigentlich hätte ich gerne alle Listenelemente bekommen und muss daher - gefühlt - einen kleinen Umweg nehmen.# Code wars IV # Problem 9: Name That Cow def codeliste_aufbauen(data): ''' Bekommt die Daten und gibt einzelne Codes in einer Liste zurück ''' data = data.replace(" ","") data = data.split("\n") if data[-1] == "0": data.pop() return data def ergebnis_ausgeben(code,namensliste): ''' Erledigt die Ausgabe in der Konsole ''' if namensliste: # Wahr, wenn die Liste nicht leer ist! print("Possible names for #{} are: {}.\n".format(code,", ".join(namensliste))) else: print("No matching names found for #{}.\n".format(code)) def vornamenliste_aufbauen(): ''' Holt sich die Daten aus den Vornamenslisten Offene Probleme: [ ] Es werden alle Namen geholt, nicht nur die, die auch möglich sind, z. B. < 10 oder ohne Leerzeichen und ohne Sonderzeichen ''' vornamen = [] dateien = ["Männliche Vornamen.txt","Weibliche Vornamen.txt"] for datei in dateien: with open(datei) as f: for line in f: line = line.replace("\n","") vornamen.append(line) vornamen.sort() # Trainingsmaterial ''' Wähle code = 382 -> EVA vornamen = ['Bob', 'Eda', 'Eda', 'Eka', 'Eka', 'Eva', 'Ewa', \ 'Ida', 'Iga', 'Ina', 'Ina', 'Ira', 'Ira', 'Isa', \ 'Isa', 'Iva', 'Lea', 'Lia', 'Mia', 'Nea', 'Nia', \ 'Noa', 'Néa', 'Oda', 'Ola', 'Ola', 'Ona', 'Oya', \ 'Pia', 'Ria', 'Rob', 'Uta'] ''' return vornamen def treffer_suchen(code,vornamen): ''' Suche alle Treffer in der Vornamensliste für den dekodierten code und gibt die Liste zurück ''' codeliste = {"2":["A","B","C"], "3":["D","E","F"], "4":["G","H","I"], "5":["J","K","L"], "6":["M","N","O"], "7":["P","Q","R"], "8":["T","U","V"], "9":["W","X","Y","Z"]} results = [] # Nimmt die Ergebnisse auf if "1" in code or "0" in code: # Der 1 sind keine Buchstaben zugeordnet return [] else: for vorname in vornamen: match = True if len(vorname) != len(code): # Kann nicht passen pass elif " " in vorname: # Kann nicht passen pass else: for letter, i in zip(list(vorname),list(code)): if not letter.upper() in codeliste[i]: match = False # Muss nicht weiterprüfen break # Nächster Vorname! if match == True: results.append(vorname) return results def main(): """ Mainfunktion """ data = """114 2662 6886 42664 42662 58473 58472 5642662 382 232 252473 727225 6424235 0""" # Übungsmaterial # data = """382""" # Daten aufbereiten codes = codeliste_aufbauen(data) vornamen = vornamenliste_aufbauen() # Treffer suchen for code in codes: treffer = treffer_suchen(code,vornamen) ergebnis_ausgeben(code,treffer) if __name__ == "__main__": main()Zu verbessern wäre hier wohl die Funktion treffer_suchen(code,vornamen). Mich würde interessieren, ob es eine bessere Lösung - z. B. mittels Datenbank oder re-Modul geben könnte. Eine Musterlösung von HP gibt es für die frühen Code wars leider noch nicht.
Keine Kommentare:
Kommentar veröffentlichen