📄 megahal.rb
字号:
# This is a port of the MegaHal chatterbot software to Ruby.# The original code can be downloaded here: http://megahal.alioth.debian.org/# This port is also based on JMegaHal, http://www.jibble.org/jmegahal/## (C) 1998 Jason Hutchens# (C) 2001-2004 Paul James Mutton# (C) 2005 Mark Kretschmann <markey@web.de>## License: GNU General Public License V2####################################################################### class Quad######################################################################class Quad def initialize(s1, s2, s3, s4) @tokens = [s1, s2, s3, s4] @canStart = false @canEnd = false end def getToken(index) return @tokens[index] end def setCanStart(flag) @canStart = flag end def setCanEnd(flag) @canEnd = flag end def canStart() return @canStart end def canEnd() return @canEnd end def hashCode() return tokens[0].hash() + tokens[1].hash() + tokens[2].hash() + tokens[3].hash() end def equals(other) equal = other.token[0] == @token[0] and other.token[1] == @token[1] and other.token[2] == @token[2] and other.token[3] == @token[3] return equal endend####################################################################### class MegaHal######################################################################class MegaHal def initialize @words = Hash.new() @quads = Hash.new() @next = Hash.new() @previous = Hash.new() end # Returns whether or not a word boundary exists in a string at the specified location. def boundary?(string, pos) alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' digit = '0123456789' if pos == 0 return false end if pos == string.length return true end if string[pos, 1] == ' ' and alpha.include?(string[pos-1, 1]) and alpha.include?(string[pos+1, 1]) return false end if pos > 1 and string[pos-1, 1] == ' ' and alpha.include?(string[pos-2, 1]) and alpha.include?(string[pos, 1]) return false end if alpha.include?(string[pos, 1]) and not alpha.include?(string[pos-1, 1]) return true end if not alpha.include?(string[pos, 1]) and alpha.include?(string[pos-1, 1]) return true end if digit.include?(string[pos, 1]) != digit.include?(string[pos-1, 1]) return true end end # Breaks a string into an array of words. def make_parts(input) input.upcase!() offset = 0 parts = Array.new() parts = input.split(' ')# loop do# if boundary?(input, offset)# # Add word to array# parts << input.slice(0..offset-1)## break if offset == input.length()# input.slice!(0..offset-1)# offset = 0# else# offset = offset+1# end# end return parts end def learn(parts) if parts.size() >= 4 i = 0 while i < parts.size()-3 quad = Quad.new(parts[i+0], parts[i+1], parts[i+2], parts[i+3]) if @quads.has_key?(quad) quad = @quads[quad] else @quads[quad] = quad end if i == 0 quad.setCanStart(true) end if i == parts.size()-4 quad.setCanEnd(true) end n = 0 while n < 4 token = parts[i+n] if not @words.has_key?(token) @words[token] = Array.new() end @words[token].push(quad) n = n+1 end if i > 0 previousToken = parts[i-1] if not @previous.has_key?(quad) @previous[quad] = Array.new() end @previous[quad].push(previousToken) end if i < parts.size()-4 nextToken = parts[i+4] if not @next.has_key?(quad) @next[quad] = Array.new() end @next[quad].push(nextToken) end i = i+1 end else puts "Parts has less than 4 elements, skipping." end end def learnFile(path) file = File.new(path, File::RDONLY) sentences = file.readlines() sentences.each do |line| unless line[0, 1] == "#" parts = make_parts(line)# print parts.size()# print parts learn(parts) end end end def generateReply(word) word.upcase!() parts = Array.new() quads = Array.new() print "Keys in @words: \n" @words.each_key { |key| print key + "\n" } if @words.has_key?(word) quads = @words[word] print "@words has the key.\n" end return "Error: quads is empty." if quads.empty?() middleQuad = quads[rand( quads.size()-1 )] quad = middleQuad 0.upto(3) do |i| parts << quad.getToken(i) end count = 0 while not quad.canEnd() print "Count: #{count}\n" count = count + 1 nextTokens = @next[quad] nextToken = nextTokens[rand( nextTokens.size()-1 )] quad = @quads[Quad.new(quad.getToken(1), quad.getToken(2), quad.getToken(3), nextToken)] parts.push(nextToken) end quad = middleQuad count = 0 while not quad.canStart() print "Count: #{count}\n" count = count + 1 previousTokens = @previous[quad] previousToken = previousTokens[rand( previousTokens.size()-1 )] quad = @quads[Quad.new(previousToken, quad.getToken(0), quad.getToken(1), quad.getToken(2))] parts.unshift(previousToken) end sentence = String.new() parts.each { |x| sentence << " " << x } sentence << "." return sentence end def do_reply(input) parts = make_parts(input) learn(parts)# output = generate_reply(@model, @words)# capitalize(output) # testing output = parts.join() return output endend####################################################################### Main######################################################################hal = MegaHal.new()hal.learnFile("megahal.trn")puts "Enter word: "text = readline().chomp()puts "\n"puts "Answer: \n"puts hal.generateReply(text)# hal = MegaHal.new()# puts "Enter text: \n"# text = readline()# puts "\n"# puts "Words: \n"# puts hal.do_reply(text)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -