2 # Author: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
3 # New markov chain plugin
19 return nil if self.empty?
22 count = rand(self.size-i)
24 count = rand([n, self.size-i].min)
56 @hash.delete(el) if @hash[el] == 0
67 @picker << [total, el]
78 return @hash.keys.first
80 make_picker unless @valid_pick
82 @picker.each { |ch, el|
83 return el if pick < ch
90 # Word or nonword regexp:
91 # can be used to scan a string splitting it into
95 attr_reader :max_order
98 @mkv = Hash.new { |hash, key|
99 hash[key] = {:prev => ChanceHash.new, :next => ChanceHash.new}
101 @mkv[nil] = ChanceHash.new
105 s = sym.to_sym rescue nil
106 @mkv[nil].increase(s)
109 def add_before(array, prev)
110 raise "Not enough words in new data" if array.empty?
111 raise "Too many words in new data" if array.size > @max_order
113 h[:prev].increase(prev)
116 def add_after(array, nxt)
117 raise "Not enough words in new data" if array.empty?
118 raise "Too many words in new data" if array.size > @max_order
120 h[:next].increase(nxt)
124 raise "Too many words in new data" if array.size > @max_order + 1
125 add_before(array.butfirst, array.first)
126 add_after(array.butlast, array.last)
137 def simple_learn(text)
138 syms = text.scan(WNW).map { |w| w.intern }
142 syms.size.times { |i|
143 ([@max_order, syms.size-i].min+1).times { |ord|
145 # puts "Learning #{v.inspect}"
152 def learn(text, o={})
153 opts = {:lowercase => false}.merge o
155 lc = opts[:lowercase]
159 simple_learn(text.downcase)
162 pp @mkv if defined? pp
165 def raw_next(syms, o={})
166 max_order = o.fetch(:max_order, @max_order)
167 ar = syms.last([max_order, syms.size].min)
169 @mkv[ar][:next].random
171 raw_next(ar.butfirst, o)
176 syms = text.scan(WNW).map { |w| w.intern }
180 def raw_prev(syms, o={})
181 max_order = o.fetch(:max_order, @max_order)
182 ar = syms.first([max_order, syms.size].min)
184 @mkv[ar][:prev].random
186 raw_prev(ar.butlast, o)
191 syms = text.scan(WNW).map { |w| w.intern }
195 def complete_prev(text, o={})
196 syms = text.scan(WNW).map { |w| w.intern }
197 prev = raw_prev(syms, o)
200 prev = raw_prev(syms, o)
205 def complete_next(text, o={})
206 syms = text.scan(WNW).map { |w| w.intern }
207 nxt = raw_next(syms, o)
210 nxt = raw_next(syms, o)
215 def complete(text, o={})
218 txt = @mkv[nil].random.to_s
220 syms = txt.scan(WNW).map { |w| w.intern }
221 prev = raw_prev(syms, o)
222 nxt = raw_next(syms, o)
224 # Keep adding only on the side where we
225 # didn't come across a nil already
228 prev = raw_prev(syms, o)
232 nxt = raw_next(syms, o)