Tekst genereren met Markovprocessen¶
Opdracht: Tekst genereren met Markovprocessen
import random
# Dit notebook staat in solutions/ en het bestand in practicals/assets/,
# vandaar het pad terug. In de opgave zelf is dat gewoon "a.txt".
A_TXT = "../practicals/assets/a.txt"
def create_dictionary(filename):
"""Maakt een dictionary die per woord bijhoudt welke woorden erop volgen
:param filename: de naam van het tekstbestand om te analyseren
:type filename: str
:rtype: dict
"""
with open(filename) as file:
text = file.read()
words_follow = {}
previous_word = "$"
for new_word in text.split():
if previous_word not in words_follow:
words_follow[previous_word] = [new_word]
else:
words_follow[previous_word] += [new_word]
previous_word = "$" if new_word[-1] in ".?!" else new_word
return words_follow
assert create_dictionary(A_TXT) == {
"krijg": ["toch"],
"voor": ["de"],
"wil": ["taarten", "42"],
"toch": ["spam"],
"Ik": ["wil", "krijg", "wil"],
"spam": ["en"],
"42": ["en", "taarten!"],
"$": ["Ik", "Ik", "Ik"],
"taarten": ["en", "voor"],
"de": ["vakantie?"],
"en": ["42", "spam.", "taarten"],
}
previous_word begint bij het startsymbool "$", en elk woord dat op een
zin-einde volgt (., ? of !) zet previous_word daar weer op terug. Zo
komt elk zinsbegin in de lijst bij "$" terecht, precies zoals het college
en de opgave het beschrijven.
De test hierboven is exact het voorbeeld uit de opgave: create_dictionary('a.txt')
levert de dictionary op die daar staat.
def generate_text(words_follow, n_words):
"""Genereert een tekst van n_words woorden met een Markovproces
:param words_follow: dictionary met woordovergangen, van create_dictionary
:type words_follow: dict
:param n_words: het aantal woorden dat gegenereerd moet worden
:type n_words: int
:rtype: str
"""
previous_word = "$"
words = []
for _ in range(n_words):
new_word = random.choice(words_follow[previous_word])
words.append(new_word)
previous_word = "$" if new_word[-1] in ".?!" else new_word
return " ".join(words)
generate_text(create_dictionary(A_TXT), 20)
'Ik wil 42 en taarten voor de vakantie? Ik krijg toch spam en 42 taarten! Ik wil 42 taarten! Ik'
generate_text draait zonder assertion: de uitvoer is willekeurig, dus er is
geen vaste uitkomst om tegen te toetsen. Wat je wel kunt controleren, is of de
cel foutloos uitvoert en of de uitvoer alleen woorden bevat die ook echt in
words_follow voorkomen - en dat volgt direct uit hoe de functie is
opgebouwd: elk woord komt uit words_follow[previous_word], nooit ergens
anders vandaan.