3 # Author: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
4 # New markov chain plugin
37 @hash.delete(el) if @hash[el] == 0
55 make_picker unless @valid_pick
57 @picker.each { |ch, el|
58 return el if pick < ch
67 # Word or nonword regexp:
68 # can be used to scan a string splitting it into
73 # mkv[i] holds the chains of order i
80 # Each chain is in the form
81 # [:array, :of, :symbols] => {
82 # :word => [chance before, chance after]
83 # :word => [chance before, chance after]
85 # except for order 0, which is just a hash of
90 s = sym.to_sym rescue nil
91 if @mkv[0].has_key?(s)
98 def add_before(array, prev)
99 raise "Not enough words in new data" if array.empty?
100 raise "Too many words in new data" if array.size > MAX_ORDER
102 if @mkv[size].has_key?(array)
103 h = @mkv[size][array]
110 @mkv[size][array.dup] = { prev => [1, 0] }
114 def add_after(array, nxt)
115 raise "Not enough words in new data" if array.empty?
116 raise "Too many words in new data" if array.size > MAX_ORDER
118 if @mkv[size].has_key?(array)
119 h = @mkv[size][array]
126 @mkv[size][array.dup] = { nxt => [0, 1] }
131 raise "Too many words in new data" if array.size > MAX_ORDER + 1
132 add_before(array.butfirst, array.first)
133 add_after(array.butlast, array.last)
144 def simple_learn(text)
145 syms = text.scan(WNW).map { |w| w.intern }
149 syms.size.times { |i|
150 [MAX_ORDER, syms.size-i].min.times { |ord|
152 # puts "Learning #{v.inspect}"
159 def learn(text, o={})
160 opts = {:lowercase => true}.merge o
162 lc = opts[:lowercase]
166 simple_learn(text.downcase)
169 pp @mkv if defined? pp
174 mkv = MarkovChainer.new
176 mkv.learn("This is a test, a nice little test indeed.")