forked from andrewsli/node-markov
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmarkov.js
137 lines (115 loc) · 3.3 KB
/
markov.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/** Textual markov chain generator */
class MarkovMachine {
/** build markov machine; read in text.*/
constructor(text) {
let words = text.split(/[ \r\n]+/);
this.words = words.filter(c => c !== "");
this.wordChain = this.makeChains();
this.bigramChain = this.makeBigramChain();
}
/** set markov chains:
*
* for text of "the cat in the hat", chains will be
* {"the": ["cat", "hat"], "cat": ["in"], "in": ["the"], "hat": [null]} */
makeChains() {
let wordChain = {}
for(let i = 0; i < this.words.length; i++){
// creates key for word if doesn't exist yet
if(!wordChain[this.words[i]]){
wordChain[this.words[i]] = []
}
// add next word into chain for current word, null if last word
if(i === this.words.length-1){
wordChain[this.words[i]].push(null)
}
else{
wordChain[this.words[i]].push(this.words[i+1])
}
}
return wordChain
}
makeBigramChain() {
let bigramChain = {};
for(let i = 1; i < this.words.length; i++){
//create bigram with current and previous word
let bigram = this.words[i-1] + " " + this.words[i]
//create key for bigram in bigramChain if doesn't exist yet
if(!bigramChain[bigram]){
bigramChain[bigram] = []
}
// add next word into value for current bigram
if(i === this.words.length-1){
bigramChain[bigram].push(null)
}
else{
bigramChain[bigram].push(this.words[i+1])
}
}
return bigramChain
}
// return random text from bigram chain
makeBigramText(numWords = 100){
if (numWords === 0) {
return;
}
let text = "";
let lastBigram = "";
let bigrams = Object.keys(this.bigramChain);
lastBigram = randomElement(bigrams);
text += capitalize(lastBigram) + " ";
let counter = 2;
while (counter < numWords){
let nextWord = randomElement(this.bigramChain[lastBigram]);
if (nextWord === null){
text = text.slice(0,-1);
break;
}
text += nextWord + " ";
counter ++;
lastBigram = splitBigram(lastBigram)[1] + " " + nextWord
}
return text;
}
/** return random text from chains, only works with single word chains*/
makeText(numWords = 100) {
if (numWords === 0) {
return;
}
let text = "";
let lastWord = "";
let words = Object.keys(this.wordChain);
lastWord = randomElement(words);
text += capitalize(lastWord) + " ";
let counter = 1;
while (counter < numWords) {
lastWord = randomElement(this.wordChain[lastWord]);
if (lastWord === null) {
text = text.slice(0,-1);
break;
}
text += lastWord + " ";
counter++;
}
return text;
}
}
// returns random element of array
function randomElement(array){
return array[Math.floor(Math.random() * array.length)];
}
// return captialized word
function capitalize(word){
return word.charAt(0).toUpperCase() + word.slice(1);
}
function splitBigram(bigram){
words = bigram.split(" ")
return words
}
module.exports = {
MarkovMachine,
randomElement,
capitalize
}
// let mm = new MarkovMachine(`Billy and the Billy trains that ever billied. How many times did Billy chase down the Billy train?`)
// console.log(mm.bigramChain)
// console.log(mm.makeBigramText());