Dies ist eine alte Version des Dokuments!
In dem Projekt Text_rein-Gedicht_raus geht es darum, einen Python-Code zu schreiben, der aus einem beliebigen Text ein Gedicht generiert. Dieses ist zwar nicht unbedingt logisch und grammatikalisch richtig, hat aber den Anschein und Klang eines richtigen Gedichtes.
Dem großen Ziel der Gedichtgenerierung sind folgende Ziele untergeordnet:
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. ### UMWANDELN VON TEXT-DATEIEN IN EINE FÜR DEN CODE VERARBEITBARE FORM ### 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. ### AUFTEILEN DES ERSTEN EINGABETEXTES IN ABSÄTZE UND EINLESEN DER JEWEILS LETZTEN WÖRTER EINES ABSATZES ### 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. ### UMWANDELN DER ORIGINALEN PHONEME DER WORTE IM REIMPOOL IN ALLGEMEINERE PHONEME ### 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. ### FESTSTELLUNG DER ANZAHL DER SILBEN ZUM VERGLEICHEN DER REIME ### 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 ###VERGLEICHEN ALLER WÖRTER AUF REIME UND IHRE SPEICHERUNG MIT IHREN MÖGLICHEN REIMPARTNERN ### 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 Phonemen """ 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 funktionen_aufrufen(worte): """ Hier werden die Funktionen toleranz_wort(wort), silbenzahl(neues_wort) und silben(neues_wort, anzahl_silben) aufgerufen, wobei jedes wort in worte einmal durch die drei Funktionen gesteckt wird, und dann wird ein Wörterbuch endungen mit den Wörtern aus worte als Keys und deren für den Reim relevante Endung als Value """ i = 1 endungen = {} # Das wird das Wörterbuch mit den Wörtern aus worte als Keys und deren für den Reim relevante #Endung als Value. while i < len(worte): # Erinnerung: Worte ist die Liste mit den Keys von ngrams also eine Liste mit den #letzen Wörtern jeder Zeile von eingabe1 --> Es wird also durch jeden potenziellen #Reim durchgelooped, damit sie bald auf Reime überprüft werden können. wort = worte[i] try: if not (wort in dictionary): # Hier wird ausgeschlossen, dass das ganze Programm abbricht, weil #wort nicht im Phonem-Wörterbuch steht. i=i+1 continue neues_wort = toleranz_wort(wort) anzahl_silben = silbenzahl(neues_wort) endsilben = silben(neues_wort, anzahl_silben) i = i +1 except IndexError: i=i+1 endungen[wort] = endsilben # Hier wird das Wörterbuch endungen erstellt, wobei die Endung endsilben ist. return endungen endungen = funktionen_aufrufen(worte) # Aufruf von funktionen_aufrufen(worte) ###ERSTELLEN DER WAHRSCHEINLICHKEITEN FÜR DIE 2-GRAMMS DER ZEILENGENERIERUNG AUS DEM ZWEITEN EINGABETEXT ### 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 ### WORT-FÜR-WORT ANHÄNGEN AN DIE REIMPAARE ZUR ZEILENGENERIERUNG NACH DEM 2-GRAMM-PRINZIP ### 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) ### GENERIERUNG DES FERTIGEN GEDICHTS ### 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=[] # Liste ohne die das nicht funktioniert... (warum eigentlich?) 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()
28.05.15
# Beispielreim: eingabe = "I'm not afraid to take a stand \n\ Everybody come take my hand \n\ We'll walk this road together, through the storm \n\ Whatever weather, cold or warm \n\ Just let you know that, you're not alone \n\ Holla if you feel that you've been down the same road" # Die Verse werden ohne Zeichen in liste_mit_eingegebenen_zeilen als einzelne Strings gespeichert: eingabe_ohne_zeichen = eingabe.replace(".", "").replace(",", "").replace("!", "").replace("?", "").replace(";", "") liste_mit_eingegebenen_zeilen = eingabe_ohne_zeichen.split(' \n ', 1000) print "Liste mit eingegebenen zeilen: \n", liste_mit_eingegebenen_zeilen, '\n' # Hier sollen die ersten Reime gefunden und in der reimliste gespeichert werden. reimliste = [] for vers1 in liste_mit_eingegebenen_zeilen: for vers2 in liste_mit_eingegebenen_zeilen: if vers1[-3:] == vers2[-3:] and vers2 != vers1 : reimliste.append(vers1) else: continue print "Reimliste: \n", reimliste
04.06.15:
11.06.15:
import pickle f=file("cmudict.dump","rb") p=pickle.Unpickler(f) betonungen=p.load() # auf das Phonem-Wörterbuch wird zugegriffen dictionary = dict(betonungen) print dictionary["laugh"] print dictionary["love"]
Das gibt aus: ['L', 'AE1', 'F'] ['L', 'AH1', 'V']
18.06.2015:
#!/usr/bin/env python # -*- coding: utf-8 -*- import copy import pickle from extractor import * songs_tss=read_songs("bobdylan.dump") eingabe = songs_tss liste_mit_eingegebenen_zeilen = [] neueliste = [] KopierteListe = [] ngrams = {} print len(eingabe) # Liste mit Liedzeilen ohne Sonderzeichen wird erzeugt. for x in range(0, len(eingabe)): eingabe_ohne_zeichen =unicode(eingabe[x].lyrics.replace(".","").replace(",","").replace("!","").replace("?","").replace(";","")) liste_mit_eingegebenen_zeilen.append(eingabe_ohne_zeichen.split("\n")) # Lyricliste kopieren, um gleich darauf eine neue Liste zu erzeugen, in der die Liste in einzelne Wörter geteilt wird for x in range(0, len(eingabe)): eingabe_ohne_zeichen =unicode(eingabe[x].lyrics.replace(".","").replace(",","").replace("!","").replace("?","").replace(";","").replace("\n"," ")) KopierteListe.append(eingabe_ohne_zeichen.split(" ")) # Erzeugung der 2grams for x in range(len(KopierteListe)): for y in range(len(KopierteListe[x])): if not(KopierteListe[x][y] in ngrams): ngrams[KopierteListe[x][y]] = [KopierteListe[x][y-1]] else: ngrams[KopierteListe[x][y]].append([KopierteListe[x][y-1]]) #Testen mit beliebig gewähltem key print ngrams["you"]
25.06.15:
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 speichert 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
02.07.15:
def toleranz_wort(wort): toleranz = { ("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"]}
06.07.15:
09.07.15:
28.07.15 (1. Projekttag):
29.07.15 (2. Projekttag):
30.07.15 (3. und letzter Projekttag):
Wir haben also einen Code, bei dem man Folgendes selbst bestimmen kann:
Hier sind nun einige Beispiele, die wir generieren konnten:
Eingabetexte: Bob Dylan; Reimschema: aabb
hope you're finally arrived indian you know i've survived lucky as you're an instant no food to change the pavement pleasant and west split and rub the hotel a hot tub something only be sprung at his fat food was hung their water in my brains the middle but then complains mississippi a job that loads i see built boats
Eingabetexte: Bob Dylan; Reimschema: aabb
there like a glance through the scars the coast of water rushed when the water hushed feelin' fine well she sleeps into dealing drugs and tips be in the penny knife what one by his life victory some more night for the dragon her head on that painted wagon of camille 'neath holes uncle took him much of souls
Eingabetexte: Bob Dylan; Reimschema: aabb
luther king and some trains and you had no brains swimmin' i could care oh the summer rich wealthy farmer farmer answers can i could get uglier i'm a-walkin' down the mirror whispered "not even started baby be an iron rotted you get it is like silk you mind clinging of milk we thought it wasn't contagious as dry was outrageous
Eingabetexte: Bob Dylan; Reimschema: aabb
next door you hear a prayer can be my record player brokin' down the mountain range fair throne and said to change gonna throw a parking meter i'll call you back the editor glowing gleaming in argentina but i was put my mind corrina you or soul our ship confused all your brownsville girl so amused criticize tell me that mistake tried to ride gonna break
Eingabetexte: Bob Dylan; Reimschema: aabb
nothin' standing i can't who's pretending it invokes it's your bed sally yourself a lonesome valley if god's in the kind favor what my dues getting braver i'll flip a pretty stars with no visible scars way of birth well my baby for the same again maybe that says hello to explode and handsome girl now corrode
Ausgangstext-Reime: Bob Dylan; Ausgangstext-Zeile: Bibel; Reimschema: abab
him a morsel of thine aunt masters according to cover a lamb for wherein the want ninety and yet will discover with fenced cities and there hang am withered it is baby and people unto their bang among the new moon maybe unto the stone for his brother serve god in argentina according to go forth and mother me in vain thing corrina a land and came out water name will give you forever that when david the daughter while ye have i will never
Ausgangstext-Reime: Bob Dylan; Ausgangstext-Zeile: Bibel; Reimschema: abab
we gave him that something cooking even if i say i scuff the rich ye are exploding for their poverty enough israel and the lord require came and lifted up the law ye shall not through desire followed me not know it's alright ma thou shalt not many and snorts the border was very act so to burn all the vain thoughts troubled i able to direct heathen and built an angel rides whom we ceased in the ocean we shall baptize you for lights it and of the night season
Ausgangstext-Reime: Eminem; Ausgangstext-Zeile: Bibel; Reimschema: aabb
kindle a sin and fetched a sign syrians and an help from mine of the god is our sister because of their register about and spotted and a young by fire as none shall be sung treasures by whatsoever craft samuel the house he will i laughed
Ausgangstext-Reime: Bibel; Ausgangstext-Zeile: Eminem; Reimschema: abab
Me plus i will he granted Can’t say that the exit wounds Am whatever your feet planted Chance I grow up touch your husbands Don’t look back tell ‘em to the sheaves Drunk and land time while they pitched Get this shit out of olives Up I hate me to be preached
Ausgangstext-Reime: Eminem; Ausgangstext-Zeile: Bibel; ; Reimschema: abab
this day that which concern i am not gonna counsel thine hand and burn wanna marijuana valley of the basket than a jackass i'm revoked vessels of the casket and hated him and smoked
Ausgangstext-Reime: Eminem; Ausgangstext-Zeile: Bibel; Reimschema: abab
Into the monotony The city of his pets Women and great company Of the land was war vets Consolation a stone unturned Two covered on anyway Speaking unto god turned But saul went in the freeway
Ausgangstext-Reime: Eminem; Ausgangstext-Zeile: Bibel; Reimschema: abab
Him against him the earth Maxine phone I’m gonna As a man have been worth The lord your marijuana The half animal caged That a convertible To make thee that engaged Ruin a cannibal
Ausgangstext-Reime: Bob Dylan; Ausgangstext-Zeile: Bibel; Reimschema: abab
God and they wanted recruits Be cut down from a just showed For we will plant pleasant fruits Generation to explode Hundred and captains and locked Many people from the cash Holy and simon peter knocked The day and I was a flash
Ausgangstext-Reime: Bob Dylan; Ausgangstext-Zeile: Bibel; Reimschema: abab
Page of a smile his wonders But the American towns My hand there’s seven thunders All loaded and twenty pounds In a jail high they removed Watered down that thou hast striven Valerie say you say to avoid To the sky with fate driven
Ausgangstext-Reime: Eminem; Ausgangstext-Zeile: Moby Dick; Reimschema: abba
No means of the trigger Sudden grunt of one dense crowd Of view of those whose loud Round the crazy nigger He placed upon first broke The oriental waters Extremities of the daughters Fishery spain our smoke
n-grams bzw. Markov-Ketten:
Hannah Hilliger, Niels Vogt