Hier eine Zusammenfassung des Aufbaus des gesamten Codes:
Zur Gedichtgenerierung benutzen wir zwei Textquellen, welche übereinstimmen können aber nicht müssen. Aus dem ersten werden die Worte genommen, die sich reimen und aus dem zweiten wird der Rest jeder Zeile generiert. Der Text für die Reime wird nach Absätzen aufgeteilt. Dann wird jeweils nur das letzte Wort von jedem Absatz in den Pool der Reime geworfen. Das machen wir, weil die Wörter, die am Ende eines Absatzes/Satzes stehen, normalerweise auch am Ende einer Gedichtzeile zu finden sind, Füllwörter oder Personalpronomen z.B. aber eher selten. Um eine sinnvolle Varianz der Reimpaare und Zeilengestaltung zu ermöglichen, müssen die Textquellen ausreichend umfangreich sein (erster Text: z.B. Liedzeilen von 100 Songs, zweiter Text: z.B. die Bibel).
Bei dem zweiten Text werden alle Wörter in den Pool geworfen, aus dem die restlichen Wörter einer Zeile kommen. Diese werden dann nach dem 2-Gramm-Prinzip hinter das Reimwort gesetzt. Sind aber die beiden Textquellen unterschiedlich und kommt das Reimwort nicht im zweiten Text vor, so wird so lange aus dem ersten Text nach 2-Gramm-Prinzip ein Wort vor das Reimwort gehängt, bis das zuletzt angehängte Wort im zweiten Text vorkommt. Danach wird alles aus dem zweiten Text dahinter gehängt, bis die vorgegebene Länge der Zeile (Vorgabe durch Anzahl der Silben) erreicht ist.
2-Gramms sind eine Form der stochastischen Textzusammensetzung. Dabei wird ein Text in Fragmente, z.B. Buchstaben, Silben oder Wörter, zerlegt und dann nach bestimmten Wahrscheinlichkeiten wieder zusammengesetzt. Die Wahrscheinlichkeiten ergeben sich aus dem Ausgangstext, indem von jedem Fragment ein Partner gespeichert wird, wie zum Beispiel das Fragment, das darauf folgt. Je nach dem wie oft dieses Paar der Fragmente nun im Ausgangstext existiert, ist die Wahrscheinlichkeit für das erneute kombinieren der Fragmente im neuen Text höher oder niedriger. Dazu muss die Textbasis natürlich genügend groß sein, da sonst alle Fragmentpaare nur einmal vorkommen und der Text somit willkürlich oder fast willkürlich zusammengesetzt wird.
Bei 3-Gramms wird nicht nur das Ausgangsfragment und sein Nachfolger gespeichert, sondern auch noch das darauf folgende. Das hat den Vorteil, dass, wenn die Fragmente Worte sind, große Teile des neu-generierten Textes grammatikalisch richtig sind. Allerdings gibt es dann 3 Worte, die im Zusammenhang stehen müssen. Daraus folgt, dass die Text-Basis noch viel größer sein muss als bei 2-Gramms, da sonst dasselbe wie bei 2-Gramms mit zu kleiner Textbasis passiert.
In unserem Projekt benutzen wir 2-Gramms für die Zeilengenerierung. Dabei besteht ein Fragment aus einem Wort und es wird das Wort davor als Partner gespeichert. Die 2-Gramms benutzen wir zum generieren der Zeilen, wobei die Reimwörter das erste Wort darstellen, zu dem ein Wort generiert wird. Wir haben uns gegen 3-Gramms entschieden, da die große Masse an Text, die man dafür bräuchte, den Rahmen unseres Projektes gesprengt hätte.
Für eine ausführliche Erklärung von n-Gramms siehe Quellen.
Unser System der Reimfindung beruht auf einem schon existierenden Wörterbuch, dass die meisten englischen Wörter mit ihren Phonemen gespeichert hat. Dies erspart uns, jegliche Buchstaben-Kombinationen, die eine unterschiedliche Schreibweise aber ähnliche Aussprache haben, selbst und von Hand zu speichern. Mit einem von uns erstellten Toleranzwörterbuch (siehe Protokoll vom 2.7.15) werden ähnliche vorgegebene Phoneme, deren Unterschiede bei Reimen unter den Tisch fallen, durch die Selben ersetzt. Also werden zwei sich reimende Silben mit gleichen Buchstaben dargestellt. Leise und für Reime eher unwichtige Buchstaben wie „R“ in „car“ werden entfernt, da sie sich in der Aussprache des Vokals widerspiegeln.
Nun werden anhand der Vokale die Silben gezählt. Dabei entspricht jeder Vokal einer Silbe. Misch-Vokale wie „AY“ oder „OW“ werden als ein Vokal gezählt. Außerdem beginnt eine Silbe immer mit einem Vokal und endet mit dem Konsonanten vor dem nächsten Vokal. Betrachtet man z.B. „dictionary“ so wird es so aufgeteilt: „d-ict-ion-ar-y“. Da der erste Buchstabe für einen Reim unwichtig ist, verlieren wir so auch keine Silbe. Anhand der Silbenanzahl zweier Wörter wird festgelegt, wie viele Silben sich reimen sollen. Wenn zum Beispiel die Worte „dictionary“ und „be“ verglichen werden, wird so erreicht, dass kein Fehler auftritt, wenn „be“ zu Ende ist, sondern dass nur „y“ und „e“ verglichen werden. Bei „dictionary“ und „solitary“ werden nur die letzten drei Silben abgeglichen, da die Wörter so lang sind. Das kann man aber variieren.
Aus den vorherigen beiden Bausteinen folgen bestimmte Voraussetzungen für die Ausgangstexte:
import random import pickle from extractor import * anzahl_reimpaare = int(raw_input("Geben Sie die Anzahl der Reime an: ")) laenge_einer_zeile = int(raw_input("Geben Sie die Anzahl der Silben pro Zeile an: "))+1 toleranz_laenge_der_zeile = int(raw_input("Geben Sie die Toleranz zur Laenge einer Zeile an: "))+1 anzahl_der_strophen = int(raw_input("Geben Sie die Anzahl der Strophen an: ")) reimschema = str(raw_input("Geben Sie ein Reimschema aabb, abab oder abba an: ")) eingabe1 = read_songs("eminem.dump") # Text, aus dem die letzten Wörter einer Zeile, also die Reime gemacht #werden. def text_einlese_fertig(): """ Liest txt-Dateien ein, und wandelt sie in die Form um, mit der wir bei den ngram-Funktionen letztewoerter(), ngramshintenmet() und ngrams_fuer_notfall_meth() arbeiten.Also wandelt die Funktion die Datei in eine Liste mit Strings um, wobei eine String ein Wort enthält """ with open ("stjamesbible.txt", "r") as bibel: text = bibel.read()# der gesamte Text wird eingelesen und es werden alle Sonderzeichen entfernt und in #kleine Buchstaben gedreht, damit das toleranz_wort damit arbeiten kann und die Anzahl #der Silben erfasst wird. liste_mit_strings = [text] import re text=re.sub(r'[^\x00-\x7F]','', text) # re entfernt weitere Sonderzeichen. for i in range(10):# in dieser und den nächsten Schleifen bis Ende, werden die Absätze, die in gesplittet #gespeichert werden durch das Trennen bei jeder Zahl /könnte auch etwas anderes sein) #erstellt. i = str(i) neue_liste_mit_strings=[] for liste in liste_mit_strings: neue_liste_mit_strings.extend(liste.split(i)) liste_mit_strings=neue_liste_mit_strings return liste_mit_strings eingabe2 = text_einlese_fertig() # diese Variable bestimmt, aus welchem Text alle Wörter hinter den Reimen #generiert werden.
liste_mit_eingegebenen_zeilen = []# ist eine Liste mit Listen,die pro Liste einen Absatz/Zeile speichert, wobei #jedes Wort in einem String steht. ngrams = {} # Hier werden am Ende von letztewoerter() alle letzten Wörter mit der Wahrscheinlichkeit ihrer #Zusammenstellung in einem Wörterbuch gespeichert, wobei jedes Wort ein Key ist, das als Value #jeweils die nächsten beiden Worte hat, die dem jeweils folgen. def letztewoerter(): """ diese Funktion liest vom Text eingabe1 alle Wörter am Ende eines Absatzes ein und macht somit den Pool, aus dem die Reimwörter kommen""" global liste_mit_eingegebenen_zeilen for x in range(0, len(eingabe1)):# in der Schleife werden wieder alle Zeichen und Absätze entfernt, #sowie alle Buchstaben in Kleinbuchstaben umgewandelt. eingabe_ohne_zeichen = eingabe1[x].lyrics.replace("."," ").replace(","," ").replace("!"," ").replace("?"," ").replace(";"," ").replace("("," ").replace(")"," ").replace("-"," ").replace('"'," ") eingabe_ohne_zeichen = eingabe_ohne_zeichen.lower() liste_mit_eingegebenen_zeilen.extend(eingabe_ohne_zeichen.split("\n")) liste_2=[] # ist eine Liste von Liste mit Strings, wobei in einer Liste eine Zeile und in ihr dann Strings #mit einer String pro Wort steht. for zeile in liste_mit_eingegebenen_zeilen: # splittet die Zeilen in Wörter, sodass jede Zeile eine Liste #mit Strings und die Strings ein Wort haben. liste_2.append(zeile.split()) liste_mit_eingegebenen_zeilen=liste_2 for x in range(0, len(liste_mit_eingegebenen_zeilen)):# nimmt jede Zeile (Liste mit Strings) und speicher die #Häufigkeit der Zusammenstellungen der letzten Wörter. try: if liste_mit_eingegebenen_zeilen[x][-1] not in ngrams:# wenn das letzte Wort der Zeile noch #nicht in ngrams ist, wird es als Key gespeichert und die Endwörter der nächsten beiden Zeilen #werden als Value gespeichert. try: ngrams[liste_mit_eingegebenen_zeilen[x][-1]] = [liste_mit_eingegebenen_zeilen[x+1][-1]] ngrams[liste_mit_eingegebenen_zeilen[x][-1]].append(liste_mit_eingegebenen_zeilen[x+2][-1]) except IndexError: continue except: continue try: # wenn das letzte Wort der Zeile schon als Key vorhanden ist, werden die Enwörter der nächsten beiden #Zeilen nur in die Liste als strings gehängt. if liste_mit_eingegebenen_zeilen[x][-1] in ngrams: try: ngrams[liste_mit_eingegebenen_zeilen[x][-1]].append(liste_mit_eingegebenen_zeilen[x+1][-1]) ngrams[liste_mit_eingegebenen_zeilen[x][-1]].append(liste_mit_eingegebenen_zeilen[x+2][-1]) except IndexError: continue except: continue return ngrams ngrams=letztewoerter() # ngrams ist also das Wörterbuch mit jedem Endwort als Key und immer den Endwörtern der #nächsten beiden Zeilen als Value.
f=file("cmudict.dump","rb") # Hier wird ein heruntergeladenes Wörterbuch (es heißt "dictionary") geöffnet, in p=pickle.Unpickler(f) # dem viele englische Wörter als Key stehen und als Value eine Liste haben, in der jeweils betonungen=p.load()# die Aussprache in Strings mit einem Phonem pro String steht. dictionary = dict(betonungen) worte = [] # Hier werden alle Zeilenendungswörter hinein gehangen, aus denen dann die Reimwörter herausgefischt for listen in ngrams: # werden. worte.append(listen) worte = [] # Hier werden alle Zeilenendungswörter hinein gehangen, aus denen dann die Reimwörter herausgefischt for listen in ngrams: # werden. worte.append(listen) def toleranz_wort(wort): """ toleranz_wort(wort) nimmt die Variable wort und sucht aus dictionary die Aussprache des Wortes heraus und wandelt die Aussprache in eine ungenauere aber reimkonforme Aussprache um """ toleranz = { # Dieses Wörterbuch beinhaltet (hoffentlich) alle Phoneme als Key und hat als Value deren #Zusammenfassungen zu ein oder zwei neuen einzelnen Phonemen, hier kann also die Toleranz von Reimen #eingestellt werden. ("G", "K", "C"): ["K"], ("F", "V"): ["F"], ("D", "T"): ["T"], ("OW1", "OW0"): ["OW"], ("AW1",): ["AO"], ("EH1","EH2", "AE1", "EH0", "AE0"): ["AE"], ("AH1", "AA1", "AA2"): ["A"], ("EY1",): ["AY"], ("AY1",): ["AI"], ("SH",): ["SH"], ("N",): ["N"], ("NG",): ["NG"], ("M",): ["M"], ("B",): ["B"], ("L",): ["L"], ("AO1",): ["Ooffen"], ("DH", "TH"): ["TH"], ("P",): ["P"], ("Y",): ["Y"], ("W", "V"): ["W"], ("IH0", "IH1", "IY0", "IY1", "IH2"): ["I"], ("ER2", "ER1"): ["E","R"], ("R",): ["R"], ("ER0",): ["O","R"], ("S", "Z"): ["S"], ("HH",): ["H"], ("JH", "CH"): ["TSCH"], ("UW1", "UW0", "AH0"): ["U"]} vokale = ["A", "E", "I", "O", "U", "AE", "ER", "OR", "OW", "AY", "Ooffen", "AO", "AI"] altes_wort = dictionary[wort] # Liste mit den ursprünglichen Phonemen von wort #zum Beispiel "charity" : ['CH', 'EH1', 'R', 'IH0', 'T', 'IY0']. neues_wort=[] # Liste mit den neuen Phonemen von wort # zum Beispiel "charity": ['TSCH', 'AE', 'R', 'I', 'T', 'I'] for i in range(len(altes_wort)): # Jedes Phonem wird in dieser Schleife durchlooped und durch die #Entsprechung in toleranz (dem Wörterbuch oben) ersetzt. for key in toleranz.keys(): for phonem in key: if altes_wort[i] == phonem: for laut in toleranz[key]: neues_wort.append(laut) else: continue for j in range(len(neues_wort)): # Hier werden alle "R" vor anderen Konsonanten und am Ende eines Wortes #entfernt, damit es bei der Reimabgleichung keine Probleme gibt, da man #diese "R" sowieso nicht beim Sprechen hört. try: if neues_wort[j] == "R" and neues_wort[j+1] not in vokale: neues_wort.remove(neues_wort[j]) elif neues_wort[-1] == "R": neues_wort.remove(neues_wort[-1]) except IndexError: pass return neues_wort # gibt also eine Liste mit Strings (ein neues Phonem pro String) zurück.
def silbenzahl(neues_wort): """ gibt die Anzahl der Silben von neues_wort (Wort mit neuen Toleranz-Phonemen) zurück """ vokale = ["A", "E", "I", "O", "U", "AE", "ER", "OR", "OW", "AY", "Ooffen", "AO", "AI"] x = 0 for letter in neues_wort: # Es werden alle Vokale gezählt, was gleich der Anzahl der Silben ist, da alle if letter in vokale: #Klangvokale mit mehr als einem richtigen Vokal vorher zusammengefasst wurden. x = x +1 return x
def silben(neues_wort, anzahl_silben): """ bestimmt mit Abhängigkeit von anzahl_silben die für einen Reim relevante Endung von neues_wort und hängt sie in die Liste silbe mit den Strings der Phoneme """ vokale = ["A", "E", "I", "O", "U", "AE", "ER", "OR", "OW", "AY", "Ooffen", "AO", "AI"] silbe = [] # hier wird am Ende die relevante Endung von neues_wort hängen. hilfsliste = [] # In diese Liste wird immer eine Liste mit einer Endung (Strings mit Phonemen) mehr (von #hinten) gehängt, wobei eine Endung immer bis einschließlich zum Vokal davor geht (Bsp. s.u.). for x in range(len(neues_wort)+1)[1:]: # Hängt die Endungen wiefolgt an: if 4 > anzahl_silben: # Hat das Wort maximal 3 Silben, werden alle Endungen bis auf den ersten #Buchstaben (wenn Konsonant) an hilfsliste gehängt, also sieht hilfsliste #dann für z.B."charity" so aus: hilfsliste = [['I'], ['I', 'T', 'I'], ['AE', 'R', 'I', 'T', 'I']]. try: if neues_wort[-x] in vokale and neues_wort[-(x+1)] not in vokale and neues_wort[-(x+2)]: hilfsliste.append(neues_wort[-x:]) elif neues_wort[-x] in vokale and neues_wort[-(x+1)] in vokale and neues_wort[-(x+2)]: hilfsliste.append(neues_wort[-x:]) except IndexError: if neues_wort[-(x+1)]not in vokale: # Prüft noch, ob erster Buchstabe Konsonant oder #Vokale ist, damit kein Vokal abgeschnitten wird. hilfsliste.append(neues_wort[-x:]) x = len(neues_wort)+1 try:# Hier wird dann die für Reimfindung relevante Endung des Wortes, also die längste #angehängte Liste für "charity" z.B.: ['AE', 'R', 'I', 'T', 'I'] an silbe. silbe = hilfsliste[-1] except IndexError: pass elif anzahl_silben > 3: # Hat neues_wort mehr als drei silben, wird das Selbe wie für maximal 3 Silben #gemacht, nur dass nach 2 Silben abgebrochen wird (mehr braucht sich nicht #zu reimen) und somit der erste Buchstabe unrelevant ist. #Hinweis: Es könnte manuell eingestellt werden, wie viel sich reimen soll. try: if neues_wort[-x] in vokale and neues_wort[-(x+1)] not in vokale: hilfsliste.append(neues_wort[-x:]) elif neues_wort[-x] in vokale and neues_wort[-(x+1)] in vokale: hilfsliste.append(neues_wort[-x:]) else: pass except IndexError: pass try: silbe = hilfsliste[1] # je größer das x in hilfsliste[x], desto länger wird die #betrachtete Endung. except IndexError: pass return silbe
def endreimerueckgabe(reime): """ Hier wird aus reime (das Wörterbuch, dass in reime_finden(endungen,worte) erstellt wird) die vorgegebene Anzahl von Reimpaaren herausgesucht und in einer Liste endreime als Strings gespeichert, wobei ein String ein Wort hat """ global reimschema # Da reimschema sonst nicht verwendbar ist. endreime = [] # Wird eine Liste mit Strings (wobei ein String pro Wort), in der die Reime immer #hintereinander stehen. i = 0 while i < len(reime): # Geht durch alle Keys (Phonem-Endungen) in reime. try: if reime[reime.keys()[i]][0] != reime[reime.keys()[i]][1]: # Wenn ein Wort ungleich dem #Nächsten ist, werden beide Worte hintereinander an endreime gehängt. endreime.append(reime[reime.keys()[i]][0]) endreime.append(reime[reime.keys()[i]][1]) i = i+1 elif reime[reime.keys()[i]][0] == reime[reime.keys()[i]][1]: # Wenn ein Wort gleich dem #Nächsten ist, wird das übernächste überprüft. Ist es immer noch gleich, geht man zur #nächsten Phonem-Endung, und ist er ungleich, so werden diese beiden Worte an endreime gehängt. if reime[reime.keys()[i]][0] != reime[reime.keys()[i]][2]: endreime.append(reime[reime.keys()[i]][1]) endreime.append(reime[reime.keys()[i]][2]) i = i+1 elif reime[reime.keys()[i]][0] == reime[reime.keys()[i]][2]: i = i+1 pass except IndexError: pass endreimeneu = [] # Hier stehen die Paare nach Reimschema sortiert, ist ansonsten das selbe wie endreime. while reimschema not in ["aabb", "abab", "abba"]: # Überprüft, ob existierendes Reimschema eingegeben wurde. reimschema = str(raw_input("Sie müssen eins dieser drei Reimschemata angeben: aabb, abab oder abba: ")) # In den nächsten drei Schleifen, werden die Reimpaare einfach in neuer Position an endreimeneu gehängt: if reimschema == "aabb": for x in range(anzahl_reimpaare): a = random.randint(0, len(endreime)//2)*2 endreimeneu.append(endreime[a]) endreimeneu.append(endreime[a+1]) elif reimschema == "abab": for x in range(anzahl_reimpaare): a = random.randint(0, len(endreime)//2)*2 b = random.randint(0, len(endreime)//2)*2 if a != b: endreimeneu.append(endreime[a]) endreimeneu.append(endreime[b]) endreimeneu.append(endreime[a+1]) endreimeneu.append(endreime[b+1]) elif a == b: x = x elif reimschema == "abba": for x in range(anzahl_reimpaare): a = random.randint(0, len(endreime)//2)*2 b = random.randint(0, len(endreime)//2)*2 if a != b: endreimeneu.append(endreime[a]) endreimeneu.append(endreime[b]) endreimeneu.append(endreime[b+1]) endreimeneu.append(endreime[a+1]) elif a == b: x = x return endreimeneu
def ngramshintenmet(): """ macht mit dem Text von eingabe2 ein Wörterbuch, in dem jedes Wort von eingabe2 als Key steht und setzt als Value eine Liste mit Strings, wobei jede String ein Wort enthält, das irgendwann mal direkt vor dem Key kommt """ liste_ohne_zeichen = [] # Liste mit Strings (eine String pro Wort), ohne Sonderzeichen und nur Kleinbuchstaben. liste_ohne_zeichen_gesplittet = [] for x in range(len(eingabe2)): # Geht durch alle Strings (eine String pro Wort)in eingabe2 durch, entfernt #alle Sonderzeichen und verwandelt alles in Kleinbuchstaben (was bei #Moby Dick und der Bibel aber schon gemacht ist) und hängt sie in #Wörter aufgesplittet an liste_ohne_zeichen. eingabe_ohne_zeichen =eingabe2[x].replace(".","").replace(",","").replace("!","").replace("?","").replace(";","").replace("("," ").replace(")"," ").replace("-"," ").replace('"'," ") eingabe_ohne_zeichen = eingabe_ohne_zeichen.lower() liste_ohne_zeichen.append(eingabe_ohne_zeichen.split()) for x in range(len(liste_ohne_zeichen)): liste_ohne_zeichen_gesplittet.extend(liste_ohne_zeichen[x]) # Die Listen von Listen von Strings #werden wieder zu Listen von Strings for x in range(len(liste_ohne_zeichen_gesplittet)): # Hier wird zu jedem Wort (String) als Key das Wort #davor als Value (Liste mit String pro Wort) gespeichert. if not(liste_ohne_zeichen_gesplittet[x] in ngramshinten): ngramshinten[liste_ohne_zeichen_gesplittet[x]] = [liste_ohne_zeichen_gesplittet[x-1]] else: ngramshinten[liste_ohne_zeichen_gesplittet[x]].append(liste_ohne_zeichen_gesplittet[x-1]) return ngramshinten
ngramshinten_fuer_notfall = {}# Wörterbuch mit jedem Wort aus eingabe1: Key: Wort als String, Value: Liste mit #Strings, wobei jedes Wort das direkt vor dem Key steht in einer String ist #(Doppelungen kommen vor). def ngramshinten_fuer_notfall_met(): """ macht das selbe wie ngramshintenmet() nur für eingabe1, denn falls es mal ein Reimwort aus eingabe1 gibt, dass nicht in eingabe2 vorkommt, wird ein Wort vor diesem Wort aus den ngrams von eingabe1 genommen""" liste_ohne_zeichen = [] liste_ohne_zeichen_gesplittet = [] for x in range(len(eingabe1)): eingabe_ohne_zeichen =eingabe1[x].lyrics.replace(".","").replace(",","").replace("!","").replace("?","").replace(";","").replace("("," ").replace(")"," ").replace("-"," ").replace('"'," ") eingabe_ohne_zeichen = eingabe_ohne_zeichen.lower() liste_ohne_zeichen.append(eingabe_ohne_zeichen.split()) for x in range(len(liste_ohne_zeichen)): liste_ohne_zeichen_gesplittet.extend(liste_ohne_zeichen[x]) for x in range(len(liste_ohne_zeichen_gesplittet)): if not(liste_ohne_zeichen_gesplittet[x] in ngramshinten_fuer_notfall): ngramshinten_fuer_notfall[liste_ohne_zeichen_gesplittet[x]] = [liste_ohne_zeichen_gesplittet[x-1]] else: ngramshinten_fuer_notfall[liste_ohne_zeichen_gesplittet[x]].append(liste_ohne_zeichen_gesplittet[x-1]) return ngramshinten_fuer_notfall ngramshinten=ngramshintenmet() endreime = endreimerueckgabe(reime)
def alle_Strophen(): """ generiert alle Strophen mit Hilfe von ErsteMet(x, toleranz_laenge_der_zeile) und gibt dann das fertige Gedicht aus """ reimende_worte = 2*anzahl_reimpaare reime_pro_strophe = reimende_worte//anzahl_der_strophen strophen = [] # Liste mit Zeilen, also Liste von Strings (ein String pro Zeile). for y in range(anzahl_der_strophen): for x in range(reime_pro_strophe): song_zeile = ErsteMet(x+y*reime_pro_strophe,toleranz_laenge_der_zeile) # es wird für jedes Reimwort #pro Strophe eine song_zeile generiert (Liste mit einer String mit einer Zeile). strophen.append(song_zeile[0]) # Die String wird an Strophe gehängt. strophen.append(" ") # Es werden Leerzeichen zwischen die Zeilen getan. strophen = "\n".join(strophen) # Jede Strophe wird durch Leerzeile getrennt. print "\n" print strophen def ErsteMet(x,toleranz_laenge_der_zeile): """ generiert zu jedem gegebenen Reimwort x abhängig von toleranz_laenge_der_zeile eine Liedzeile """ song_zeile=[] zeilen = [] # Am Ende Liste mit einem String, der Liedzeile enthält. zeilen.append(endreime[x]) # Jeder Endreim wird einmal beim neuen Aufrufen dieser Funktion an zeilen #gehängt. i = silbenzahl(toleranz_wort(endreime[x])) # Silbenzahl des Wortes while i <= laenge_einer_zeile: # Beschränkt die Länge einer Zeile try: # Hier wird immer zufällig das vorherige Wort gesucht. vorheriges_wort = random.choice(ngramshinten[zeilen[0]]) except KeyError: # Existiert kein vorheriges Wort in eingabe2, so wird das aus eingabe1 genommen. ngramshinten_fuer_notfall = ngramshinten_fuer_notfall_met() vorheriges_wort = random.choice(ngramshinten_fuer_notfall[zeilen[0]]) if vorheriges_wort == zeilen[0]: # damit nicht zweimal das selbe Wort hintereinander im Gedicht sind, # wird, falls das Wort und dessen Vorgänger gleich sind, nochmal gezogen. i = i else: try: # Da die Wörter nicht gleich sind, wird jetzt das ausgesuchte vorherige Wort davor #gehängt,falls dadurch nicht die vorgegebene Zeilenlänge überschritten wird. i = i + silbenzahl(toleranz_wort(vorheriges_wort.lower())) zeilen.insert(0, vorheriges_wort) except KeyError: try: # Wird die Zeilenlänge überschritten, so kann das Wort trotzdem angehängt werden, #wenn es nicht länger als die vorgegebene Toleranz ist und die Zeile ist fertig. if silbenzahl(toleranz_wort(vorheriges_wort.lower())) <= toleranz_laenge_der_zeile: zeilen.insert(0, vorheriges_wort).join i = laenge_einer_zeile + 1 except KeyError: # Ist das vorherige Wort länger als toleranz_laenge_der_zeile, so #wird nochmal gezogen. i = i # toleranz_laenge_der_zeile. zeilen = " ".join(zeilen) # Leerzeichen zwischen die Strings (also die Wörter), zeilen = "".join(zeilen) #alle Wörter mit Leerzeichen dazwischen werden in eine String gepackt. song_zeile.append(zeilen) return song_zeile alle_Strophen()
Den gesamten unkommentierten Code zum Anschauen gibt es hier: http://mintgruen.tu-berlin.de/mathesisWiki/lib/exe/fetch.php?media=gedichtausgabe_unkommentiert.py