-
Notifications
You must be signed in to change notification settings - Fork 1
/
markov.rb
executable file
·110 lines (84 loc) · 2 KB
/
markov.rb
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
#!/usr/bin/ruby
require './morpheme'
class Markov
include Morpheme
ENDMARK = '%END%'
CHAIN_MAX = 30
def initialize
@dic = {}
@starts = {}
end
def register(line)
lines = line.chomp.split(/[。??!! ]+/)
lines.each do |line|
next if line.empty?
morphemes = Morpheme::analyze(line)
add_sentence(morphemes)
end
end
#parts: [
# ['I', 'noun'], - prefix1
# ['am', '-'], - prefix2
# ['a' , '-'],
# ['boy', 'noun']
# ]
def add_sentence(morphemes)
return if morphemes.size < 3
morphemes = morphemes.dup
prefix1 = morphemes.shift[0].split(/\t/)[0]
prefix2 = morphemes.shift[0].split(/\t/)[0]
add_start(prefix1)
morphemes.each do |suffix|
suffix = suffix[0].split(/\t/)[0]
if suffix == ""
add_suffix(prefix1, prefix2, ENDMARK)
next
end
add_suffix(prefix1, prefix2, suffix)
prefix1, prefix2 = prefix2, suffix
end
end
def generate(keyword)
return nil if @dic.empty?
words = []
prefix1 = (@dic[keyword])? keyword : select_start
prefix2 = select_random(@dic[prefix1].keys)
words.push(prefix1, prefix2)
CHAIN_MAX.times do
suffix = select_random(@dic[prefix1][prefix2])
break if suffix == ENDMARK
words.push(suffix)
prefix1, prefix2 = prefix2, suffix
end
return words.join
end
def add_suffix(prefix1, prefix2, suffix)
@dic[prefix1] = {} unless @dic[prefix1]
@dic[prefix1][prefix2] = [] unless @dic[prefix1][prefix2]
@dic[prefix1][prefix2].push(suffix)
end
def add_start(prefix1)
@starts[prefix1] = 1 unless @starts[prefix1]
#@starts[prefix1] += 1
end
def select_start
return select_random(@starts.keys)
end
def select_random(ary)
return ary[rand(ary.size)]
end
def load(file)
open(file, 'r') do |fp|
@dic = Marshal::load(fp)
@starts = Marshal::load(fp)
end
end
def save(file)
open(file, 'w') do |fp|
Marshal::dump(@dic, fp)
Marshal::dump(@starts, fp)
end
end
attr_reader :dic
attr_writer :load, :save
end