在文本文件中,我们试图创建一个马尔科夫模型来查找字母过渡的概率。但是,我们在将字母过渡放入单独的词典时遇到了困难。例如,所有以 "e" 开头的过渡都应该被放入一个词典中,而所有以 "t"、"s"、"a" 和 "m" 开头的过渡应该被放入其他词典中。
2. 解决方案:
为了解决这个问题,我们可以创建一个名为
Markov 的类,它包含一个 lookup 词典来存储字母过渡。这个词典的键是字母的组合,而值是字母的列表。我们可以通过使用 nwise 函数将文本中的字母分组为组合来填充这个词典。然后,我们就可以使用 gen_text 函数来生成基于这些字母过渡的随机文本。
from random import choice
import re
from collections import defaultdict
from itertools import chain, tee, izip
def strip_non_alpha(text, reg=re.compile('[^a-z']+', re.IGNORECASE)):
return reg.sub(' ', text.strip())
def nwise(iterable, n):
"s -> (s0,s1, ... sn-1), (s1,s2, ... sn), (s2, s3, ... sn+1), ..."
args = tee(iterable, n)
for i,t in enumerate(args):
for j in range(i):
next(t, None)
return izip(*args)
class Markov:
CHAINLEN = 3
PRE = ' '*(CHAINLEN - 1)
@classmethod
def from_file(cls, fname):
with open(fname) as inf:
return Markov(inf)
def __init__(self, text):
"""
Create a new Markov chain model
text
Either a string or a sequence of strings
"""
self.lookup = defaultdict(list)
self.words = 0
self.strings = 0
if hasattr(text, '__iter__'):
for s in text:
self.add_text(s)
else:
self.add_text(text)
def add_text(self, text):
"""
Add a string to the lookup table
text
string to add
"""
text = strip_non_alpha(text).lower()
self.words += len(text.split())
self.strings += 1
for chars in nwise(chain(Markov.PRE, text, Markov.PRE), Markov.CHAINLEN):
stem = ''.join(chars[:-1])
self.lookup[stem].append(chars[-1])
def gen_text(self, upto=200):
"""
Generate a string
upto
maximum length of string to be generated
"""
s = Markov.PRE
res = []
for i in range(upto + Markov.CHAINLEN):
ch = choice(self.lookup[s])
res.append(ch)
s = s[1:] + ch
if s == Markov.PRE: # terminal string
break
return ''.join(res[:-(Markov.CHAINLEN - 1)])
def __str__(self):
return '\n'.join("'{}': {}".format(k, self.lookup[k]) for k in sorted(self.lookup))
def main():
# mc = Markov.from_file('markov.txt')
mc = Markov('Steam,Teams,Meets,Teems,Eat,Ate,State,Tease,Test,Mast,Mates'.split(','))
print mc.strings, mc.words
print mc
for i in range(10):
print(mc.gen_text())
if __name__=="__main__":
main()
通过使用这个解决方案,我们可以将字母过渡放入单独的词典中,并使用它们来生成随机文本。