Markov chain text generator: Difference between revisions

→‎{{header|Python}}: Added a functional variant, defining nGramsFromWords in terms of zipWithN/starmap
No edit summary
(→‎{{header|Python}}: Added a functional variant, defining nGramsFromWords in terms of zipWithN/starmap)
Line 947:
 
=={{header|Python}}==
===Procedural===
Markov text generator - Python implementation.<br>
Usage: markov.py source.txt context length
Line 1,022 ⟶ 1,023:
you're a humbug? asked Dorothy. A balloon, said Oz, for I have no right to command them
once</pre>
 
===Functional===
Defining an '''nGramFromWords''' function in terms of itertools.starmap
(used with a generalized '''zipWithN''' wrapper).
 
<lang python>from functools import (reduce)
from itertools import (starmap)
from random import (choice)
from textwrap import (fill)
 
from os.path import (expanduser)
from os import (getcwd)
 
 
# markovText :: Dict -> [String] -> ([String] -> Bool) -> IO [String]
def markovText(dct):
'''Word-hashed nGram dict -> opening words -> end condition -> text'''
 
n = len(list(dct.keys())[0].split())
 
# step :: [String] -> [String]
def step(xs):
return xs + [choice(dct[' '.join(xs[-n:])])]
return lambda ws: lambda p: (
until(p)(step)(ws)
)
 
 
# main :: IO ()
def main():
nGramLength = 2
dctNGrams = markovRules(nGramLength)(
readFile(getcwd() + '/' + 'alice_oz.txt').split()
)
print (wordWrapped(75)(' '.join(
markovText(dctNGrams)(
nGramWithInitialCap(dctNGrams)
)(sentenceEndAfterMinWords(200))
)))
 
 
# markovRules :: Int -> [String] -> Dict
def markovRules(n):
'''All words in ordered list hashed by preceding nGrams of length n'''
def nGramKey(dct, tpl):
k = ' '.join(list(tpl[:-1]))
dct[k] = (dct[k] if k in dct else []) + [tpl[-1]]
return dct
return lambda ws: reduce(
nGramKey,
nGramsFromWords(1 + n)(ws),
{}
)
 
 
# nGramsFromWords :: Int -> [String] -> [Tuple]
def nGramsFromWords(n):
'''List of nGrams, of length n, derived from ordered list of words ws'''
return lambda ws: zipWithN(lambda *xs: xs)(
map(lambda i: ws[i:], range(0, n))
)
 
 
# nGramWithInitialCap :: Dict -> [String]
def nGramWithInitialCap(dct):
'''Random pick from nGrams which start with capital letters'''
return choice(list(filter(
lambda w: 1 < len(w) and w[0].isupper() and w[1].islower(),
dct.keys()
))).split()
 
 
# sentenceEndAfterMinWords :: Int -> [String] -> Bool
def sentenceEndAfterMinWords(n):
'''Predicate :: Sentence punctuation after minimum word count'''
return lambda ws: n <= len(ws) and (
ws[-1][-1] in ['.', "'", '!', '?']
)
 
 
# GENERIC -------------------------------------------------
 
# readFile :: FilePath -> IO String
def readFile(fp):
with open(
expanduser(fp), 'r', encoding='utf-8'
) as f:
return f.read()
 
 
# until :: (a -> Bool) -> (a -> a) -> a -> a
def until(p):
def go(f, x):
v = x
while not p(v):
v = f(v)
return v
return lambda f: lambda x: go(f, x)
 
 
# wordWrapped :: Int -> [String] -> String
def wordWrapped(n):
return lambda s: fill(s, width=n)
 
 
# zipWithN :: (a -> b -> ... -> c) -> ([a], [b] ...) -> [c]
def zipWithN(f):
return lambda tplLists: list(
starmap(f, zip(*tplLists))
)
 
 
if __name__ == '__main__':
main()</lang>
{{Out}}
<pre>Soup! Who cares for fish, Game, or any place in order to start, for she was
losing her temper. 'Are you to destroy her. But until she starts back to
this country alone, and cannot love. I pray you to obey you? Oh, yes; I am
sure we shall be very unhappy unless you give me brains, and very soon
found out a box of comfits, (luckily the salt water had not gone much
farther before she could do to ask: perhaps I shall not be afraid. One by
one the mice to the Witch of the pole stuck up its back. While Dorothy was
shocked to see Oz, he said, 'on and off, for days and four kinds of cake
and four nights, hammering and twisting and bending and soldering and
polishing and pounding at the picture.) 'Up, lazy thing!' said the Hatter,
it woke up again with a trumpet in one great flock of wild crows flew in
one corner. She lay down to breakfast, after which she concluded that it
will not send me back to Kansas, I hope it won't float, remarked Dorothy,
it will be a kinder and more sounds of broken glass. 'What a curious plan!'</pre>
 
=={{header|REXX}}==
9,659

edits