Markov chain text generator: Difference between revisions

 
(16 intermediate revisions by 10 users not shown)
Line 46:
Probably you want to call your program passing those numbers as parameters. Something like: markov( "text.txt", 3, 300 )
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F makerule(data, context)
‘Make a rule dict for given data.’
[String = [String]] rule
V words = data.split(‘ ’)
V index = context
 
L(word) words[index ..]
V key = (words[index - context .< index]).join(‘ ’)
I key C rule
rule[key].append(word)
E
rule[key] = [word]
index++
 
R rule
 
F makestring(rule, length)
‘Use a given rule to make a string.’
V oldwords = random:choice(Array(rule.keys())).split(‘ ’)
V string = oldwords.join(‘ ’)‘ ’
 
L 0 .< length
X.try
V key = oldwords.join(‘ ’)
V newword = random:choice(rule[key])
string ‘’= newword‘ ’
 
L(word) 0 .< oldwords.len
oldwords[word] = oldwords[(word + 1) % oldwords.len]
oldwords.last = newword
 
X.catch KeyError
R string
R string
 
V data = File(‘alice_oz.txt’).read()
V rule = makerule(data, 3)
V string = makestring(rule, 100)
V max_line_size = 100
V cur_line_size = 0
L(word) string.split(‘ ’)
I cur_line_size + word.len >= max_line_size
print()
cur_line_size = 0
cur_line_size += word.len + 1
print(word, end' ‘ ’)
print()</syntaxhighlight>
 
{{out}}
<pre>
awakened from his sleep, and seeing all these mice around him he gave one bark of delight and
jumped right into the middle of a river. I am afraid I shall never have any brains, after all! Down
the stream the raft floated, and the poor little thing sat down and looked along the passage into
the loveliest garden you ever saw. How she longed to get out again. Suddenly she came upon a little
three-legged table, all made of china, even to their clothes, and were so small that he dropped
almost as many as he put in the basket. Then, being
</pre>
 
=={{header|C sharp|C#}}==
<syntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
 
namespace MarkovChainTextGenerator {
class Program {
static string Join(string a, string b) {
return a + " " + b;
}
 
static string Markov(string filePath, int keySize, int outputSize) {
if (keySize < 1) throw new ArgumentException("Key size can't be less than 1");
 
string body;
using (StreamReader sr = new StreamReader(filePath)) {
body = sr.ReadToEnd();
}
var words = body.Split();
if (outputSize < keySize || words.Length < outputSize) {
throw new ArgumentException("Output size is out of range");
}
 
Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();
for (int i = 0; i < words.Length - keySize; i++) {
var key = words.Skip(i).Take(keySize).Aggregate(Join);
string value;
if (i + keySize < words.Length) {
value = words[i + keySize];
} else {
value = "";
}
 
if (dict.ContainsKey(key)) {
dict[key].Add(value);
} else {
dict.Add(key, new List<string>() { value });
}
}
 
Random rand = new Random();
List<string> output = new List<string>();
int n = 0;
int rn = rand.Next(dict.Count);
string prefix = dict.Keys.Skip(rn).Take(1).Single();
output.AddRange(prefix.Split());
 
while (true) {
var suffix = dict[prefix];
if (suffix.Count == 1) {
if (suffix[0] == "") {
return output.Aggregate(Join);
}
output.Add(suffix[0]);
} else {
rn = rand.Next(suffix.Count);
output.Add(suffix[rn]);
}
if (output.Count >= outputSize) {
return output.Take(outputSize).Aggregate(Join);
}
n++;
prefix = output.Skip(n).Take(keySize).Aggregate(Join);
}
}
 
static void Main(string[] args) {
Console.WriteLine(Markov("alice_oz.txt", 3, 200));
}
}
}</syntaxhighlight>
{{out}}
<pre>axes,' said the Duchess, who seemed ready to agree to everything that Alice said; 'there's a large mustard-mine near here. And the moral of that is-Be what you would seem to be-or if you'd like it put more simply-Never imagine yourself not to be alive. Those creatures frightened me so badly that I cannot keep my promises. I think you are wrong to want a heart. It makes most people unhappy. If you only knew it, you are in luck not to have a heart. I have played Wizard for so many years that I may be as other men are. Why should I give you fair warning,' shouted the Queen, stamping on the ground as she spoke; 'either you or your head must be off, and that the pail was lying in several small pieces, while the poor milkmaid had a nick in her left elbow. There! cried the milkmaid angrily. See what you have done! she screamed. In a minute I shall melt away. I'm very sorry, returned Dorothy. Please forgive us. But the pretty milkmaid was much too wise not to swim, and he was obliged to call to her to help him up again. Why didn't</pre>
 
=={{header|C++}}==
In this implementation there is no repeated suffixes!
 
<langsyntaxhighlight lang="cpp">
#include <ctime>
#include <iostream>
Line 127 ⟶ 258:
return 0;
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 146 ⟶ 277:
tin arms and
</pre>
 
=={{header|C#|C sharp}}==
<lang csharp>using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
 
namespace MarkovChainTextGenerator {
class Program {
static string Join(string a, string b) {
return a + " " + b;
}
 
static string Markov(string filePath, int keySize, int outputSize) {
if (keySize < 1) throw new ArgumentException("Key size can't be less than 1");
 
string body;
using (StreamReader sr = new StreamReader(filePath)) {
body = sr.ReadToEnd();
}
var words = body.Split();
if (outputSize < keySize || words.Length < outputSize) {
throw new ArgumentException("Output size is out of range");
}
 
Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();
for (int i = 0; i < words.Length - keySize; i++) {
var key = words.Skip(i).Take(keySize).Aggregate(Join);
string value;
if (i + keySize < words.Length) {
value = words[i + keySize];
} else {
value = "";
}
 
if (dict.ContainsKey(key)) {
dict[key].Add(value);
} else {
dict.Add(key, new List<string>() { value });
}
}
 
Random rand = new Random();
List<string> output = new List<string>();
int n = 0;
int rn = rand.Next(dict.Count);
string prefix = dict.Keys.Skip(rn).Take(1).Single();
output.AddRange(prefix.Split());
 
while (true) {
var suffix = dict[prefix];
if (suffix.Count == 1) {
if (suffix[0] == "") {
return output.Aggregate(Join);
}
output.Add(suffix[0]);
} else {
rn = rand.Next(suffix.Count);
output.Add(suffix[rn]);
}
if (output.Count >= outputSize) {
return output.Take(outputSize).Aggregate(Join);
}
n++;
prefix = output.Skip(n).Take(keySize).Aggregate(Join);
}
}
 
static void Main(string[] args) {
Console.WriteLine(Markov("alice_oz.txt", 3, 200));
}
}
}</lang>
{{out}}
<pre>axes,' said the Duchess, who seemed ready to agree to everything that Alice said; 'there's a large mustard-mine near here. And the moral of that is-Be what you would seem to be-or if you'd like it put more simply-Never imagine yourself not to be alive. Those creatures frightened me so badly that I cannot keep my promises. I think you are wrong to want a heart. It makes most people unhappy. If you only knew it, you are in luck not to have a heart. I have played Wizard for so many years that I may be as other men are. Why should I give you fair warning,' shouted the Queen, stamping on the ground as she spoke; 'either you or your head must be off, and that the pail was lying in several small pieces, while the poor milkmaid had a nick in her left elbow. There! cried the milkmaid angrily. See what you have done! she screamed. In a minute I shall melt away. I'm very sorry, returned Dorothy. Please forgive us. But the pretty milkmaid was much too wise not to swim, and he was obliged to call to her to help him up again. Why didn't</pre>
 
=={{header|Crystal}}==
<langsyntaxhighlight lang="ruby">class Markov(N)
@dictionary = Hash(StaticArray(String, N), Array(String)).new { [] of String }
 
Line 265 ⟶ 321:
chain = Markov(3).new
chain.parse("alice_oz.txt")
puts chain.generate(200)</langsyntaxhighlight>
{{out}}
<pre>tired. I'll tell you my story. So they sat down and listened while he told the following story: I was born in Omaha-- Why, that isn't very far from Kansas! cried Dorothy. No, but I am sure we shall sometime come to some place. But day by day passed away, and they found themselves in the midst of a strange people, who, seeing me come from the big Head; so she took courage and answered: I am Dorothy, answered the girl, if he will see you, said the soldier who had taken her message to the Wizard, although he does not like to go back to Oz, and claim his promise. Yes, said the Woodman, so get behind me and I will tell you my story. So they sat down upon the bank and gazed wistfully at the Scarecrow until a Stork flew by, who, upon seeing them, stopped to rest at the water's edge. Who are you and where are you going? My name is Dorothy, said the girl, let us go. And she handed the basket to the Scarecrow. There were no fences at all by the roadside now, and the land was rough and untilled. Toward evening</pre>
 
 
=={{header|D}}==
{{trans|Kotlin}}
<langsyntaxhighlight Dlang="d">import std.file;
import std.random;
import std.range;
Line 322 ⟶ 377:
void main() {
writeln(markov("alice_oz.txt", 3, 200));
}</langsyntaxhighlight>
{{out}}
<pre>neighbour to tell him. 'A nice muddle their slates'll be in before the trial's over!' thought Alice. One of the jurors had a pencil that squeaked. This of course, Alice could not think of any good reason, and as the monster crawls through the forest he seizes an animal with a leg and drags it to his ear. Alice considered a little, and then said 'The fourth.' 'Two days wrong!' sighed the Hatter. 'I deny it!' said the March Hare. 'Sixteenth,' added the Dormouse. 'Write that down,' the King replied. Here the other guinea-pig cheered, and was immediately suppressed by the officers of the court, all dressed in green clothes and had greenish skins. They looked at Dorothy again. Why should I do this for you? asked the Scarecrow. You are quite welcome to take my head off, as long as the tiger had said, and its body covered with coarse black hair. It had a great longing to have for her own the Silver Shoes had fallen off in her flight through the air, and on the morning of the second day I awoke and found the oil-can, and then she had to stop and untwist it. After a</pre>
 
=={{header|F Sharp}}==
<syntaxhighlight lang="fsharp">
let ngram len source i = source |> List.skip i |> List.take len
let trailing len source = ngram len source (Seq.length source - len)
let leading = List.take
 
let buildMap prefixLen source =
let add map sequence =
let prefix = leading (Seq.length sequence - 1) sequence
let suffix = Seq.last sequence
let existingSuffixes = map |> Map.tryFind prefix |> Option.defaultValue []
// add a suffix to existing suffixes, probably creating duplicated entries
Map.add prefix (suffix :: existingSuffixes) map
let ngramCount = Seq.length source - prefixLen
Seq.init ngramCount (ngram (prefixLen + 1) source) |> Seq.fold add (Map[])
 
let generate outputLenLimit seed map =
let random = System.Random()
let pickSuffix prefix =
let randomItem suffixes = List.item (List.length suffixes |> random.Next) suffixes
// as the list of suffixes contains duplicates, probability of any distinct word
// is proportional to its frequency in the source text
map |> Map.tryFind prefix |> Option.map randomItem
let prefixLen = Seq.length seed
let add list word = list @ [word]
let append output _ =
trailing prefixLen output |> pickSuffix |> Option.map (add output) |> Option.defaultValue output
Seq.init outputLenLimit id |> Seq.fold append seed
 
let markov prefixLen outputLenLimit source =
let map = buildMap prefixLen source
let seed = leading prefixLen source
generate outputLenLimit seed map |> String.concat " "
 
"alice_oz.txt"
|> System.IO.File.ReadAllText
|> (fun t -> t.Split ' ')
|> List.ofSeq
|> markov 2 100
</syntaxhighlight>
{{out}}
<pre>
Alice was more dreadful than any of them. Brains are the only things in the forest a few happy days at the Scarecrow replied; but I must admit. Can't you see these are my friends, for all we know. But the girl in any other city, replied Oz; but when oil was poured upon it with a laugh, and that I may become as much as she passed; it was just beginning to feel very uneasy: to be said. At last the Gryphon whispered in reply, 'for fear they should forget them before the door, she ran out to look over their"
</pre>
=={{header|Factor}}==
{{works with|Factor|0.99 2019-10-06}}
<syntaxhighlight lang="factor">USING: assocs fry grouping io io.encodings.ascii io.files kernel
make math random sequences splitting ;
 
: build-markov-assoc ( path n -- assoc )
[ ascii file-contents " " split harvest ] dip 1 + clump
H{ } clone tuck [ [ unclip-last swap ] dip push-at ] curry
each ;
 
: first-word ( assoc -- next-key ) random concat unclip , ;
 
: next-word ( assoc key -- next-key )
[ of random ] keep unclip , swap suffix ;
 
: markov ( path n #words -- )
[ build-markov-assoc ] dip '[
dup first-word _ [ dupd next-word ] times
] { } make 2nip " " join print ;
 
"alice_oz.txt" 3 200 markov</syntaxhighlight>
{{out}}
<pre>
sight, they were getting so far off). 'Oh, my poor little feet, I wonder who will put on your shoes and stockings for you now, dears? I'm sure I don't want to live here, cried Dorothy. I want to go! Let me see: four times five is twelve, and four times six is thirteen, and four times six is thirteen, and four times seven is-oh dear! I shall be glad to give you some. And I want him to give me a heart, said the Woodman. So he walked to the edge of the desert, so she may know a way to carry you to the City of Oz in less than no time she'd have everybody executed, all round. (It was this last remark that had made her so savage when they met in the house, Let us both go to law: I will prosecute you. -Come, I'll take no denial; We must have a prize herself, you know,' said Alice to herself. 'Shy, they seem to put everything upon Bill! I wouldn't be in Bill's place for a good deal: this fireplace is narrow, to be sure; but I think I could, if I only knew how to begin.'
</pre>
 
=={{header|Fennel}}==
<syntaxhighlight lang="fennel">(fn string.split [self sep]
"Tokenize a string using the given separator."
(let [pattern (string.format "([^%s]+)" sep)
fields {}]
(self:gsub pattern (fn [c] (tset fields (+ 1 (length fields)) c)))
fields))
 
(fn read-file [filename]
"Read a file as a string. Doesn't do any error checking."
(with-open [fin (io.open filename)]
(fin:read :a)))
 
(fn random-key [table]
"Pick a random key from a non-sequential table."
;Collect keys into sequential table.
(let [keys (icollect [k _ (pairs table)] k)]
;Return a random key.
(. keys (math.random (length keys)))))
 
(fn cat-tables [t1 t2]
"Concatenate two sequential tables into a new table."
;Copy table 1 to create a result table.
(var result [(table.unpack t1)])
;Append each item of table 2 into the result.
(each [_ v (ipairs t2)]
(table.insert result v))
;Return the result.
result)
 
(fn make-rule [str context]
"Make a rule table for a given string and context length."
(var key "")
(var rule {})
(let [words (str:split " ")]
;Loop through word list.
(each [index word (ipairs [(table.unpack words (+ 1 context))])]
;Join previous words into key.
(set key (table.concat words " " index (+ index (- context 1))))
;Append word to existing key or add to a new key.
(if (. rule key)
(table.insert (. rule key) word)
(tset rule key [word]))))
;Return final rule.
rule)
 
(fn make-string [rule size]
"Make a string from a rule table up to the given size. May break early."
(var result [])
(var words [])
(var old-words (: (random-key rule) :split " "))
(var key (table.concat old-words " "))
;Loop until early break or size reached.
(for [i 1 size :until (= nil (. rule key))]
;Add to the result a random word from the list words for that key.
(set words (. rule key))
(table.insert result (. words (math.random (length words))))
;Shift the key to the next word.
(set old-words (cat-tables [(table.unpack old-words 2)]
[(. result (length result))]))
(set key (table.concat old-words " ")))
;Return the final string.
(table.concat result " "))
 
;;; Test the generator.
(print (make-string (make-rule (read-file "alice_oz.txt") 2) 300))</syntaxhighlight>
 
{{out}}
(Newlines added for readability.)
<pre>'Come, let's try Geography. London is the use of a hen that had a vague sort of
chance of a big room with a melancholy tone: 'it doesn't seem to be no worse off
than before, as the March Hare interrupted in a moment: she looked down at my
best one day, for I have to eat the comfits: this caused some noise and
confusion, as the rest of the legs and fierce eyes and roll off the fire, since
your tastes are so very angry that she could do that in a way to kill the Wicked
Witch of the East was dead the Munchkins sent a swift messenger to me, for Oz so
long and tiresome walk through the trees and began an account of the Munchkins,
who had expected her to begin.' For, you see, Alice had got its head to it, by
means of the Gates. No one has ever crossed the desert, so she made a hearty
supper and was going on. There was a little uneasily. Oh, yes; but one Wicked
Witch dies you will be the lovely Lady I shall get on my toes or sticks a pin
into me, it doesn't understand</pre>
 
=={{header|Go}}==
<langsyntaxhighlight Golang="go">package main
 
import (
Line 516 ⟶ 735:
}
return append(slice, value)
}</langsyntaxhighlight>
{{out|input=-n=3 -runs=3 -words=12 -capital -sentence}}
<pre>Alice could speak again. The Mock Turtle went on at last, more calmly, though still sobbing a little now and then, and holding it to his ear.
Line 527 ⟶ 746:
This seems to be reasonably close to the specification:
 
<langsyntaxhighlight Jlang="j">require'web/gethttp'
 
setstats=:dyad define
Line 560 ⟶ 779:
end.
;:inv phrase { words
)</langsyntaxhighlight>
 
{{out}}<langsyntaxhighlight Jlang="j"> 2 1 50 setstats 'http://paulo-jorente.de/text/alice_oz.txt'
genphrase''
got in as alice alice
Line 568 ⟶ 787:
perhaps even alice
genphrase''
pretty milkmaid alice</langsyntaxhighlight>
 
And, using 8 word suffixes (but limiting results to a bit over 50 words):
 
{{out}}<langsyntaxhighlight Jlang="j"> 2 8 50 setstats 'http://paulo-jorente.de/text/alice_oz.txt'
genphrase''
added it alice was beginning to get very tired of this i vote the young lady tells us alice was beginning to get very tired of being such a tiny little thing it did not take her long to find the one paved with yellow bricks within a short time
Line 578 ⟶ 797:
the raft through the water they got along quite well alice was beginning to get very tired of this i vote the young lady tells us alice was beginning to get very tired of being all alone here as she said this last word two or three times over to
genphrase''
gown that alice was beginning to get very tired of sitting by her sister on the bank and alice was beginning to get very tired of being such a tiny little thing it did so indeed and much sooner than she had accidentally upset the week before oh i beg</langsyntaxhighlight>
 
(see talk page for discussion of odd line wrapping with some versions of Safari)
Line 585 ⟶ 804:
{{trans|Kotlin}}
{{works with|Java|8}}
<langsyntaxhighlight Javalang="java">import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
Line 648 ⟶ 867:
System.out.println(markov("alice_oz.txt", 3, 200));
}
}</langsyntaxhighlight>
{{out}}
<pre>Emerald City is? Certainly, answered the Queen; but it is a lucky thing I am not, for my mouth is only painted, and if I ever get my heart? Or I my courage? asked the Lion in surprise, as he watched her pick up the Scarecrow and said: Come with me, for Oz has made me its ruler and the people gazed upon it with much curiosity. The Tin Woodman appeared to think deeply for a moment. Then he said, The Winkies were sorry to have them go, and they had grown so large in the last few minutes that she wasn't a bit afraid of interrupting him,) 'I'll give him sixpence. I don't believe there's an atom of meaning in it.' The jury all wrote down on their slates, and then added them up, and reduced the answer to it?' said the Mock Turtle. 'No, no! The adventures first,' said the Gryphon hastily. 'Go on with the next verse,' the Gryphon repeated impatiently: 'it begins I passed by his garden, and marked, with one eye,</pre>
 
=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
 
'''Works with jq, the C implementation of jq'''
 
'''Works with gojq, the Go implementation of jq'''
 
In the following, the initial word phrase is chosen so that it might
look like the beginning of a sentence.
 
Since jq does not include a PRN generator, an external source of entropy such as /dev/urandom is assumed.
A suitable invocation of jq would be along the lines of:
<pre>
< /dev/urandom tr -cd '0-9' | fold -w 1 | $jq -Rcnr --rawfile text alice_oz.txt -f mc.jq
</pre>
<syntaxhighlight lang="jq">
# If using gojq:
def keys_unsorted: keys;
 
 
### Pseuo-random numbers
 
# Output: a prn in range(0;$n) where $n is `.`
def prn:
if . == 1 then 0
else . as $n
| ([1, (($n-1)|tostring|length)]|max) as $w
| [limit($w; inputs)] | join("") | tonumber
| if . < $n then . else ($n | prn) end
end;
 
def sample:
if length == 0 # e.g. null or []
then null
else .[length|prn]
end;
 
 
### The tasks
 
# The words in $text
def words:
[$text | sub("\\s*$";"") | splits(" *")];
 
def markov($keySize; $outputSize):
if $keySize < 1
then "Key size can't be less than 1" | error
else words as $words
| ($words|length|length) as $wordCount
| if $outputSize < $keySize or $outputSize > $wordCount
then "Requested output size is greater than the number of words in the given text" | error
else
(reduce range(0; 1+$wordCount - $keySize) as $i ( {};
($words[$i:$i + $keySize] | join(" ")) as $prefix
| (if ($i + $keySize < $wordCount) then $words[$i + $keySize] else "" end) as $suffix
| .[$prefix] += [$suffix] )) as $dict
| { output: [] }
| ($dict|keys_unsorted) as $keys
# Start with a capitalized word, possibly following a quotation mark:
| .prefix = ($keys | map(select(test("^['A-Z][^.]*$"))) | sample)
| .output += (.prefix|split(" "))
| last(label $out
| foreach range(1; 1+$wordCount) as $n (.;
($dict[.prefix]|sample) as $nextWord
| if $nextWord | length == 0
then ., break $out
else .output += [$nextWord]
| if (.output|length) >= $outputSize
then ., break $out
else .prefix = (.output[$n:$n + $keySize] | join(" "))
end
end ))
| .output[:$outputSize] | join(" ")
end
end ;
 
markov(3; 100)
</syntaxhighlight>
{{output}}
<pre>
I am made of straw and cannot be easily damaged. There are worse
things in the world. Dorothy did not know this, and was full of smoke
from one end to the truck. Of course the truck was all ready for
them. They came from all directions, and there were thousands of them:
big mice and little mice and middle-sized mice; and each one of them
found himself lodged in a very humble tone, going down on one knee as
he spoke, and added 'It isn't a letter, after all: it's a set of
verses.' 'Are they in the prisoner's
</pre>
=={{header|Julia}}==
{{works with|Julia|0.6}}
 
<langsyntaxhighlight lang="julia">function markovtext(txt::AbstractString, klen::Integer, maxchlen::Integer)
words = matchall(r"\w+", txt)
dict = Dict()
Line 680 ⟶ 988:
 
txt = readstring(download("http://paulo-jorente.de/text/alice_oz.txt"))
println(markovtext(txt, 3, 200))</langsyntaxhighlight>
 
{{out}}
Line 687 ⟶ 995:
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.3.10
 
import java.io.File
Line 725 ⟶ 1,033:
fun main() {
println(markov("alice_oz.txt", 3, 100))
}</langsyntaxhighlight>
 
Sample output:
Line 738 ⟶ 1,046:
Computes keys of all lengths <= N. During text generation, if a key does not exist in the dictionary, the first (least recent) word is removed, until a key is found (if no key at all is found, the program terminates).
 
<langsyntaxhighlight Lualang="lua">local function pick(t)
local i = math.ceil(math.random() * #t)
return t[i]
Line 825 ⟶ 1,133:
end
io.write('\n')
</syntaxhighlight>
</lang>
 
{{out}}
Line 845 ⟶ 1,153:
she comes, to-' At this moment Five, who had been greatly interested in
</pre>
 
=={{header|Nim}}==
{{trans|Kotlin}}
<syntaxhighlight lang="nim">
import random, sequtils, strutils, tables
 
proc markov(filePath: string; keySize, outputSize: Positive): string =
 
let words = filePath.readFile().strip(false, true).splitWhitespace()
doAssert outputSize in keySize..words.len, "Output size is out of range"
 
var dict: Table[string, seq[string]]
 
for i in 0..(words.len - keySize):
let prefix = words[i..<(i+keySize)].join(" ")
let suffix = if i + keySize < words.len: words[i + keySize] else: ""
dict.mgetOrPut(prefix, @[]).add suffix
 
var output: seq[string]
var prefix = toSeq(dict.keys).sample()
output.add prefix.split(' ')
 
for n in 1..words.len:
let nextWord = dict[prefix].sample()
if nextWord.len == 0: break
output.add nextWord
if output.len >= outputSize: break
prefix = output[n..<(n + keySize)].join(" ")
 
result = output[0..<outputSize].join(" ")
 
 
const MaxLineSize = 100
 
randomize()
let result = markov("alice_oz.txt", 3, 100)
var start = 0
while start < result.len:
var idx = if start + MaxLineSize <= result.high: result.rfind(' ', start, start + MaxLineSize)
else: result.high
if idx < 0: idx = result.high
echo result[start..idx]
start = idx + 1</syntaxhighlight>
 
{{out}}
<pre>ground was carpeted with them. There were big yellow and white and blue and purple blossoms, besides
great clusters of scarlet poppies, which were so brilliant in color they almost dazzled Dorothy's
eyes. Aren't they beautiful? the girl asked, as she breathed in the spicy scent of the flowers, and
here they laid her gently on the forehead. Where her lips touched the girl they left a round,
shining mark, as Dorothy found out soon after. The road to the City of Emeralds. Perhaps Oz will
help you. Where is this great spider of yours now? asked the Tin Woodman.</pre>
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use strict;
use warnings;
 
Line 885 ⟶ 1,244:
}
 
print join(' ', @chain) . "\n";</langsyntaxhighlight>
{{out}}
<pre>Alice was thoroughly puzzled. 'Does the boots and shoes,' the Gryphon whispered in a fight with another hedgehog, which seemed to extend to the South Country? To see the Great Oz was ready to sink into the garden, where Alice could see or feel was the end of you, as she chose, she ran after her. 'I've something important to say!' This sounded promising, certainly: Alice turned and walked through the forest very thick on this side, and it seemed to Alice as she chose, she ran out and shone brightly. So they all spoke at once, I'll chop it down, and the Dormouse sulkily remarked, 'If you please, sir-' The Rabbit started violently, dropped the white kid gloves and the four travelers walked up to the Land of Oz in less than no time to think about stopping herself before she made a dreadfully ugly child: but it is a man,' said the Stork, as she spoke. 'I must be a person of authority among them, called out, 'Sit down, all of them expected to come out of breath, and till the Pigeon in a sorrowful tone; 'at least there's no use to me they flew away with me,' thought Alice,</pre>
 
=={{header|Perl 6}}==
{{Works with|rakudo|2017-01}}
<lang perl6>unit sub MAIN ( :$text=$*IN, :$n=2, :$words=100, );
 
sub add-to-dict ( $text, :$n=2, ) {
my @words = $text.words;
my @prefix = @words.rotor: $n => -$n+1;
 
(%).push: @prefix Z=> @words[$n .. *]
}
 
my %dict = add-to-dict $text, :$n;
my @start-words = %dict.keys.pick.words;
my @generated-text = lazy |@start-words, { %dict{ "@_[ *-$n .. * ]" }.pick } ...^ !*.defined;
 
put @generated-text.head: $words;
</lang>
<pre>>perl6 markov.p6 <alice_oz.txt --n=3 --words=200
Scarecrow. He can't hurt the straw. Do let me carry that basket for you. I shall not mind it, for I can't get tired. I'll tell you what I think, said the little man. Give me two or three pairs of tiny white kid gloves: she took up the fan and gloves, and, as the Lory positively refused to tell its age, there was no use in saying anything more till the Pigeon had finished. 'As if it wasn't trouble enough hatching the eggs,' said the Pigeon; 'but I must be very careful. When Oz gives me a heart of course I needn't mind so much. They were obliged to camp out that night under a large tree in the wood,' continued the Pigeon, raising its voice to a whisper. He is more powerful than they themselves, they would surely have destroyed me. As it was, I lived in deadly fear of them for many years; so you can see for yourself. Indeed, a jolly little clown came walking toward them, and Dorothy could see that in spite of all her coaxing. Hardly knowing what she did, she picked up a little bit of stick, and held it out to
</pre>
 
=={{header|Phix}}==
This was fun! (easy, but fun)
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>integer fn = open("alice_oz.txt","rb")
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
string text = get_text(fn)
<span style="color: #008080;">constant</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"now he is gone she said he is gone for good"</span>
close(fn)
<span style="color: #004080;">string</span> <span style="color: #000000;">text</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span><span style="color: #0000FF;">?</span><span style="color: #000000;">s</span><span style="color: #0000FF;">:</span><span style="color: #7060A8;">get_text</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"alice_oz.txt"</span><span style="color: #0000FF;">))</span>
sequence words = split(text)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">words</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">)</span>
 
function markov(integer n, m)
<span style="color: #008080;">function</span> <span style="color: #000000;">markov</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
integer dict = new_dict(), ki
<span style="color: #004080;">integer</span> <span style="color: #000000;">dict</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">(),</span> <span style="color: #000000;">ki</span>
sequence key, data, res
<span style="color: #004080;">sequence</span> <span style="color: #000000;">key</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">res</span>
string suffix
<span style="color: #004080;">string</span> <span style="color: #000000;">suffix</span>
for i=1 to length(words)-n do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
key = words[i..i+n-1]
<span style="color: #000000;">key</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">..</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
suffix = words[i+n]
<span style="color: #000000;">suffix</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">n</span><span style="color: #0000FF;">]</span>
ki = getd_index(key,dict)
<span style="color: #000000;">ki</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
if ki=0 then
<span style="color: #008080;">if</span> <span style="color: #000000;">ki</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
data = {}
<span style="color: #000000;">data</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
else
<span data style="color: getd_by_index(ki,dict)#008080;">else</span>
<span style="color: #000000;">data</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd_by_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ki</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
setd(key,append(data,suffix),dict)
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">),</span><span style="color: #000000;">suffix</span><span style="color: #0000FF;">),</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
integer start = rand(length(words)-n)
<span style="color: #004080;">integer</span> <span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
key = words[start..start+n-1]
<span style="color: #000000;">key</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">start</span><span style="color: #0000FF;">..</span><span style="color: #000000;">start</span><span style="color: #0000FF;">+</span><span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
res = key
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">)</span>
for i=1 to m do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">m</span> <span style="color: #008080;">do</span>
ki = getd_index(key,dict)
<span style="color: #000000;">ki</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
if ki=0 then exit end if
<span style="color: #008080;">if</span> <span style="color: #000000;">ki</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
data = getd_by_index(ki,dict)
<span style="color: #000000;">data</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd_by_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ki</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dict</span><span style="color: #0000FF;">)</span>
suffix = data[rand(length(data))]
<span style="color: #000000;">suffix</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">))]</span>
res = append(res,suffix)
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">suffix</span><span style="color: #0000FF;">)</span>
key = append(key[2..$],suffix)
<span style="color: #000000;">key</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$],</span><span style="color: #000000;">suffix</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return join(res)
<span style="color: #008080;">return</span> <span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
 
?markov(2,100)</lang>
<span style="color: #0000FF;">?</span><span style="color: #000000;">markov</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">100</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
from the alice_oz.txt file:
Line 956 ⟶ 1,296:
tears seemed to Alice a good dinner."
</pre>
Under pwa/p2js with more limited input the output could be anything between and beyond
<pre>
`gone for good`
`said he is gone she said he is gone she said he is gone she said he is gone she said he is gone for good`
</pre>
 
=={{header|PHP}}==
 
<syntaxhighlight lang="php"><?php
 
// Automated text generator using markov chain
function markovChainTextGenerator($text, $keySize, $maxWords) {
 
// Create list of tokens
$token = array();
$position = 0;
$maxPosition = strlen($text);
while ($position < $maxPosition) {
if (preg_match('/^(\S+)/', substr($text, $position, 25), $matches)) {
$token[] = $matches[1];
$position += strlen($matches[1]);
}
elseif (preg_match('/^(\s+)/', substr($text, $position, 25), $matches)) {
$position += strlen($matches[1]);
}
else {
die(
'Unknown token found at position ' . $position . ' : ' .
substr($text, $position, 25) . '...' . PHP_EOL
);
}
}
 
// Create Dictionary
$dictionary = array();
for ($i = 0 ; $i < count($token) - $keySize ; $i++) {
$prefix = '';
$separator = '';
for ($c = 0 ; $c < $keySize ; $c++) {
$prefix .= $separator . $token[$i + $c];
$separator = '.';
}
$dictionary[$prefix][] = $token[$i + $keySize];
}
 
// Starting token
$rand = rand(0, count($token) - $keySize);
$startToken = array();
for ($c = 0 ; $c < $keySize ; $c++) {
array_push($startToken, $token[$rand + $c]);
}
 
// Create Text
$text = implode(' ', $startToken);
$words = $keySize;
do {
$tokenKey = implode('.', $startToken);
$rand = rand(0, count($dictionary[$tokenKey]) - 1);
$newToken = $dictionary[$tokenKey][$rand];
$text .= ' ' . $newToken;
$words++;
array_shift($startToken);
array_push($startToken, $newToken);
} while($words < $maxWords);
return $text;
 
}
 
srand(5678);
 
$text = markovChainTextGenerator(
file_get_contents(__DIR__ . '/inc/alice_oz.txt'),
3,
308
);
 
echo wordwrap($text, 100, PHP_EOL) . PHP_EOL;</syntaxhighlight>
 
{{out}}
<pre>As soon as they heard her orders they ran away in every direction as fast as they could, Dorothy
only stopping once to pick a beautiful flower; and after a time the ladder was ready. The Scarecrow
climbed up the ladder first, but he was so anxious to get the new house and my wife as soon as
possible. The Lion hesitated no longer, but drank till the dish was empty. How do you do? I'm pretty
well, thank you, replied Dorothy politely. How do you do? I'm not feeling well, said the wolf, and
he dashed away at full speed, followed by the others. It was lucky the Scarecrow and the Tin
Woodman, for we certainly must climb over the wall. When they were on, Dorothy could not take them
off had she wished, but of course she did not wish to leave her little dog behind. Toto had run into
the crowd to bark at the birds sitting there. Dorothy went to the Witch's castle, where he was
placed in a small yard with a high arched room, the walls of which glistened with countless
emeralds. Before them stood a little man about the same height as herself; and when she had made out
the proper way of nursing it, (which was to twist it up into a sort of lullaby to it as she did not
notice when the Scarecrow stumbled into a hole and rolled over to the other side of the Tin Woodman,
sadly; for he is much too heavy to carry I shall have to think about that, replied the little old
woman as her only friend. No, I cannot do that, she replied, but I will give you some supper and a
place to pass the night with you, if you will only hold fast to the tip of my tail.</pre>
 
=={{header|Python}}==
Line 962 ⟶ 1,397:
Usage: markov.py source.txt context length
 
<syntaxhighlight lang="python">import random, sys
<lang python>#Import libraries.
import sys
import random
 
 
def readdata(file):
'''Read file and return contents.'''
with open(file) as f:
contents = f.read()
return contents
 
 
def makerule(data, context):
Line 1,012 ⟶ 1,437:
 
if __name__ == '__main__':
datawith = readdataopen(sys.argv[1], encoding='utf8') as f:
data = f.read()
rule = makerule(data, int(sys.argv[2]))
string = makestring(rule, int(sys.argv[3]))
print(string)</langsyntaxhighlight>
 
{{out}}
Line 1,039 ⟶ 1,465:
 
{{Works with|Python|3.7}}
<langsyntaxhighlight lang="python">'''Markov chain text generation'''
 
from os.path import (expanduser)
Line 1,170 ⟶ 1,596:
 
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>Markov chain text generation:
Line 1,192 ⟶ 1,618:
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">#lang racket
 
(define (pick xs) (list-ref xs (random (length xs))))
Line 1,218 ⟶ 1,644:
(values (append (rest prefix) (list suffix)) (cons suffix out))))
 
(markov "alice_oz.txt" 3 300)</langsyntaxhighlight>
 
{{out}}
<pre>
"The Scarecrow, who was never tired, stood up in another corner and waited patiently until it chose to speak again. In a minute I shall melt away. I'm very sorry, indeed, said Dorothy, who was truly sorry for him. If you will help me sew the silk together, we will begin to work on our balloon. So Dorothy took a needle and thread, and as fast as Oz cut the strips of silk into proper shape the girl sewed them neatly together. First there was a body to cut it off from: that he had never had to do such a thing before, and he wasn't going to begin again, it was very like having a game of croquet she was playing against herself, for this curious child was very fond of pretending to be two people. 'But it's no use going back to yesterday, because I was a young man when the balloon brought me here, and I am only a little girl. But you were strong enough to kill the Wicked Witch of the East, and promised her two sheep and a cow if she would prevent the marriage. Thereupon the Wicked Witch and setting them free from bondage. So she chose a number of the Winkies she will find you, and make you all her slaves. Perhaps not, said the Scarecrow, in a grieved tone; you're a humbug. Exactly so! declared the little man, rubbing his hands together as if it were not one of the shoes she owned half the power of the Golden Cap; but if she could only get back to Kansas. The Silver Shoes, said the Good Witch, have wonderful powers. And one of the eyes slowly wink at her. She thought she must have a basket to ride in, he said. So he sent the"
</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
{{Works with|rakudo|2017-01}}
<syntaxhighlight lang="raku" line>unit sub MAIN ( :$text=$*IN, :$n=2, :$words=100, );
 
sub add-to-dict ( $text, :$n=2, ) {
my @words = $text.words;
my @prefix = @words.rotor: $n => -$n+1;
 
(%).push: @prefix Z=> @words[$n .. *]
}
 
my %dict = add-to-dict $text, :$n;
my @start-words = %dict.keys.pick.words;
my @generated-text = lazy |@start-words, { %dict{ "@_[ *-$n .. * ]" }.pick } ...^ !*.defined;
 
put @generated-text.head: $words;
</syntaxhighlight>
<pre>>raku markov.raku <alice_oz.txt --n=3 --words=200
Scarecrow. He can't hurt the straw. Do let me carry that basket for you. I shall not mind it, for I can't get tired. I'll tell you what I think, said the little man. Give me two or three pairs of tiny white kid gloves: she took up the fan and gloves, and, as the Lory positively refused to tell its age, there was no use in saying anything more till the Pigeon had finished. 'As if it wasn't trouble enough hatching the eggs,' said the Pigeon; 'but I must be very careful. When Oz gives me a heart of course I needn't mind so much. They were obliged to camp out that night under a large tree in the wood,' continued the Pigeon, raising its voice to a whisper. He is more powerful than they themselves, they would surely have destroyed me. As it was, I lived in deadly fear of them for many years; so you can see for yourself. Indeed, a jolly little clown came walking toward them, and Dorothy could see that in spite of all her coaxing. Hardly knowing what she did, she picked up a little bit of stick, and held it out to
</pre>
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/*REXX program produces a Markov chain text from a training text using a text generator.*/
parse arg ord fin iFID seed . /*obtain optional arguments from the CL*/
if ord=='' | ord=="," then ord= 3 /*Not specified? Then use the default.*/
Line 1,263 ⟶ 1,711:
end /*k*/
if g\=='' then say g /*There any residual? Then display it.*/
return /* [↑] limits G to terminal width.*/</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Line 1,284 ⟶ 1,732:
{{trans|Python}}
{{works with|Rust|1.32 nightly (2018 edition)}}
<langsyntaxhighlight lang="rust">use std::env;
use std::fs;
 
Line 1,364 ⟶ 1,812:
sample(&mut rng, max, 1).into_vec()[0]
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,372 ⟶ 1,820:
=={{header|Sidef}}==
{{trans|Perl}}
<langsyntaxhighlight lang="ruby">func build_dict (n, words) {
var dict = Hash()
words.each_cons(n+1, {|*prefix|
Line 1,399 ⟶ 1,847:
}
 
say chain.join(' ')</langsyntaxhighlight>
 
{{out}}
Line 1,409 ⟶ 1,857:
{{trans|Python}}
{{works with|Swift|4.2}}
<langsyntaxhighlight lang="swift">import Foundation
 
func makeRule(input: String, keyLength: Int) -> [String: [String]] {
Line 1,453 ⟶ 1,901:
let str = makeString(rule: rule, length: 300)
 
print(str)</langsyntaxhighlight>
 
{{out}}
<pre>$ ./main /path/to/alice_oz.txt
with a crash, whereupon the Scarecrow's clothes fell out of the clouds to rule over us. Still, for many days they grieved over the loss of my heart. While I was in love I was the happiest man on earth; but no one came near them nor spoke to them because of the great beam the house rested on, two feet were sticking out, shod in silver shoes with pointed toes. Oh, dear! Oh, dear! cried Dorothy, clasping her hands together in dismay. The house must have fallen on her. Whatever shall we do? There is nothing to be done, I wonder?' As she said this, she looked up, but it was the first to break the silence. 'What day of the month is it?' he said, turning to Alice as it spoke. 'As wet as ever,' said Alice in a piteous tone. And she thought of herself, 'I wish the creatures wouldn't be so stingy about it, you know-' She had quite forgotten the Duchess by this time, and was going to dive in among the leaves, which she found to be nothing but the stars over them; and they rested very well indeed. In the morning they traveled on until they came to the great Throne Room, where he saw, sitting in the emerald throne, a most lovely Lady. She was dressed in a green uniform and wearing a long green beard. Here are strangers, said the Guardian of the Gates lived. This officer unlocked their spectacles to put them back in his great box, and then he struck at the Tin Woodman passed safely under it. Come on! he shouted to the others. These she also led to rooms, and each one of them can explain it,' said the King, 'and don't look at me like that!' He got behind</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-str}}
<syntaxhighlight lang="wren">import "io" for File
import "random" for Random
import "./str" for Strs
 
var markov = Fn.new { |filePath, keySize, outputSize|
if (keySize < 1) Fiber.abort("Key size can't be less than 1")
var words = File.read(filePath).trimEnd().split(" ")
var wordCount = words.count
if (outputSize < keySize || outputSize > wordCount) Fiber.abort("Output size is out of range")
var dict = {}
for (i in 0..(wordCount - keySize)) {
var prefix = Strs.join(words[i...i + keySize], " ")
var suffix = (i + keySize < wordCount) ? words[i + keySize] : ""
if (!dict.containsKey(prefix)) dict[prefix] = []
dict[prefix].add(suffix)
}
var output = []
var r = Random.new()
var prefix = r.sample(dict.keys.toList)
output.addAll(prefix.split(" "))
for (n in 1..wordCount) {
var nextWord = r.sample(dict[prefix].toList)
if (nextWord.isEmpty) break
output.add(nextWord)
if (output.count >= outputSize) break
prefix = Strs.join(output[n...n + keySize], " ")
}
return Strs.join(output.take(outputSize).toList, " ")
}
 
System.print(markov.call("alice_oz.txt", 3, 100))</syntaxhighlight>
 
{{out}}
<pre>
Alice with one finger; and the whole party swam to the shore. They were indeed a queer-looking party that assembled on the bank-the birds with draggled feathers, the animals with their fur clinging close to them, and all dripping wet, cross, and uncomfortable. The first question of course was, how to get back to the road from which the river had carried them. It was a very difficult game indeed. The players all played at once without waiting for the end of the table. 'Have some wine,' the March Hare said to itself in a whisper.) 'That would be grand,
</pre>
2,442

edits