2 # Author: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
3 # New markov chain plugin
41 @hash.delete(el) if @hash[el] == 0
63 return @hash.keys.first
65 make_picker unless @valid_pick
67 @picker.each { |ch, el|
68 return el if pick < ch
78 # Word or nonword regexp:
79 # can be used to scan a string splitting it into
84 # mkv[i] holds the chains of order i
87 # Each chain is in the form
88 # [:array, :of, :symbols] => {
89 # :prev => ChanceHash,
92 # except for order 0, which is a simple ChanceHash
96 @mkv[0] = ChanceHash.new
98 @mkv[i] = Hash.new { |hash, key|
99 hash[key] = {:prev => ChanceHash.new, :next => ChanceHash.new}
107 s = sym.to_sym rescue nil
111 def add_before(array, prev)
112 raise "Not enough words in new data" if array.empty?
113 raise "Too many words in new data" if array.size > MAX_ORDER
115 h = @mkv[size][array.dup]
116 h[:prev].increase(prev)
119 def add_after(array, nxt)
120 raise "Not enough words in new data" if array.empty?
121 raise "Too many words in new data" if array.size > MAX_ORDER
123 h = @mkv[size][array.dup]
124 h[:next].increase(nxt)
128 raise "Too many words in new data" if array.size > MAX_ORDER + 1
129 add_before(array.butfirst, array.first)
130 add_after(array.butlast, array.last)
141 def simple_learn(text)
142 syms = text.scan(WNW).map { |w| w.intern }
146 syms.size.times { |i|
147 [MAX_ORDER, syms.size-i].min.times { |ord|
149 # puts "Learning #{v.inspect}"
156 def learn(text, o={})
157 opts = {:lowercase => true}.merge o
159 lc = opts[:lowercase]
163 simple_learn(text.downcase)
166 pp @mkv if defined? pp
170 ar = syms.last([MAX_ORDER, syms.size].min)
175 if @mkv[ord].key?(ar)
176 @mkv[ar][:next].random
178 raw_next(ar.last(ord-1))
184 syms = text.scan(WNW).map { |w| w.intern }