3 # Author: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
4 # New markov chain plugin
38 @hash.delete(el) if @hash[el] == 0
60 return @hash.keys.first
62 make_picker unless @valid_pick
64 @picker.each { |ch, el|
65 return el if pick < ch
75 # Word or nonword regexp:
76 # can be used to scan a string splitting it into
81 # mkv[i] holds the chains of order i
84 # Each chain is in the form
85 # [:array, :of, :symbols] => {
86 # :prev => ChanceHash,
89 # except for order 0, which is a simple ChanceHash
93 @mkv[0] = ChanceHash.new
95 @mkv[i] = Hash.new { |hash, key|
96 hash[key] = {:prev => ChanceHash.new, :next => ChanceHash.new}
104 s = sym.to_sym rescue nil
108 def add_before(array, prev)
109 raise "Not enough words in new data" if array.empty?
110 raise "Too many words in new data" if array.size > MAX_ORDER
112 h = @mkv[size][array.dup]
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 = @mkv[size][array.dup]
121 h[:next].increase(nxt)
125 raise "Too many words in new data" if array.size > MAX_ORDER + 1
126 add_before(array.butfirst, array.first)
127 add_after(array.butlast, array.last)
138 def simple_learn(text)
139 syms = text.scan(WNW).map { |w| w.intern }
143 syms.size.times { |i|
144 [MAX_ORDER, syms.size-i].min.times { |ord|
146 # puts "Learning #{v.inspect}"
153 def learn(text, o={})
154 opts = {:lowercase => true}.merge o
156 lc = opts[:lowercase]
160 simple_learn(text.downcase)
163 pp @mkv if defined? pp
168 mkv = MarkovChainer.new
170 mkv.learn("This is a test, a nice little test indeed.")