-
Notifications
You must be signed in to change notification settings - Fork 2
/
Markov.class.php
78 lines (67 loc) · 2.19 KB
/
Markov.class.php
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
<?php
/**
* php-markov
*
* Tiny Markov chain implementation for PHP.
*
* @package php-markov
* @subpackage Common
* @author Kenny <0@kenny.cat>
*/
class Markov {
public $chain = array();
/**
* Training
*
* Adds the given string to the chain currently defined in this class.
*
* @param string $message The message to be added to the markov chain.
* @return true if string added, false if string empty.
*/
public function train($message) {
if(empty($message)) return false;
$array = explode(" ", $message);
foreach($array as $num => $val) {
$commit = (isset($this->chain[$val]) ? $this->chain[$val] : array()); // if there is already a block for this word, keep it, otherwise create one
$next = $array[$num + 1]; // the next word after the one currently selected
if(empty($next)) continue; // if this word is EOL, continue to the next word
if(isset($commit[$next])) $commit[$next]++; // if the word already exists, increase the weight
else $commit[$next] = 1; // otherwise save the word with a weight of 1
$this->chain[$val] = $commit; // commit to the chain
}
return true;
}
/**
* Generate text
*
* Generates a random string using the markov chain.
*
* @param int $maxWords Maximum number of words to be returned (may return less).
* @return str if generation successful, false if chain empty.
*/
public function generateText($maxWords) {
if(empty($this->chain)) return false;
$out = array_rand($this->chain); // initial word
while($out = $this->weighAndSelect($this->chain[$out])) {
$text[] = $out;
if(count($text) > $maxWords) break;
}
return implode(" ", $text);
}
/**
* Weigh and select
*
* Resolves weighing of words and returns a random one. Used by generateText.
*
* @param array $block Array with words as the index and their weight as the value.
* @return str next word to follow or false if empty block given.
*/
private function weighAndSelect($block) {
if(empty($block)) return false;
foreach($block as $key => $weight) {
for($i = 1; $i <= $weight; $i++) $tmp[] = $key;
}
$rand = array_rand($tmp);
return $tmp[$rand];
}
}