1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
class MathPlugin < Plugin
@@digits = {
"first" => "1",
"second" => "2",
"third" => "3",
"fourth" => "4",
"fifth" => "5",
"sixth" => "6",
"seventh" => "7",
"eighth" => "8",
"ninth" => "9",
"tenth" => "10",
"one" => "1",
"two" => "2",
"three" => "3",
"four" => "4",
"five" => "5",
"six" => "6",
"seven" => "7",
"eight" => "8",
"nine" => "9",
"ten" => "10"
};
def help(plugin, topic="")
"math <expression>, evaluate mathematical expression"
end
def privmsg(m)
unless(m.params)
m.reply "incorrect usage: " + help(m.plugin)
return
end
expr = m.params.dup
@@digits.each {|k,v|
expr.gsub!(/\b#{k}\b/, v)
}
while expr =~ /(exp ([\w\d]+))/
exp = $1
val = Math.exp($2).to_s
expr.gsub!(/#{Regexp.escape exp}/, "+#{val}")
end
while expr =~ /^\s*(dec2hex\s*(\d+))\s*\?*/
exp = $1
val = sprintf("%x", $2)
expr.gsub!(/#{Regexp.escape exp}/, "+#{val}")
end
expr.gsub(/\be\b/, Math.exp(1).to_s)
while expr =~ /(log\s*((\d+\.?\d*)|\d*\.?\d+))\s*/
exp = $1
res = $2
if res == 0
val = "Infinity"
else
val = Math.log(res).to_s
end
expr.gsub!(/#{Regexp.escape exp}/, "+#{val}")
end
while expr =~ /(bin2dec ([01]+))/
exp = $1
val = join('', unpack('B*', pack('N', $2)))
val.gsub!(/^0+/, "")
expr.gsub!(/#{Regexp.escape exp}/, "+#{val}")
end
expr.gsub!(/ to the power of /, " ** ")
expr.gsub!(/ to the /, " ** ")
expr.gsub!(/\btimes\b/, "*")
expr.gsub!(/\bdiv(ided by)? /, "/ ")
expr.gsub!(/\bover /, "/ ")
expr.gsub!(/\bsquared/, "**2 ")
expr.gsub!(/\bcubed/, "**3 ")
expr.gsub!(/\bto\s+(\d+)(r?st|nd|rd|th)?( power)?/, "**\1 ")
expr.gsub!(/\bpercent of/, "*0.01*")
expr.gsub!(/\bpercent/, "*0.01")
expr.gsub!(/\% of\b/, "*0.01*")
expr.gsub!(/\%/, "*0.01")
expr.gsub!(/\bsquare root of (\d+)/, "\1 ** 0.5 ")
expr.gsub!(/\bcubed? root of (\d+)/, "\1 **(1.0/3.0) ")
expr.gsub!(/ of /, " * ")
expr.gsub!(/(bit(-| )?)?xor(\'?e?d( with))?/, "^")
expr.gsub!(/(bit(-| )?)?or(\'?e?d( with))?/, "|")
expr.gsub!(/bit(-| )?and(\'?e?d( with))?/, "& ")
expr.gsub!(/(plus|and)/, "+")
if (expr =~ /^\s*[-\d*+\s()\/^\.\|\&\*\!]+\s*$/ &&
expr !~ /^\s*\(?\d+\.?\d*\)?\s*$/ &&
expr !~ /^\s*$/ &&
expr !~ /^\s*[( )]+\s*$/)
begin
debug "evaluating expression \"#{expr}\""
answer = eval(expr)
if answer =~ /^[-+\de\.]+$/
answer = sprintf("%1.12f", answer)
answer.gsub!(/\.?0+$/, "")
answer.gsub!(/(\.\d+)000\d+/, '\1')
if (answer.length > 30)
answer = "a number with >30 digits..."
end
end
m.reply answer
rescue Exception => e
puts "couldn't evaluate expression \"#{m.params}\": #{e}"
m.reply "illegal expression \"#{m.params}\""
return
end
else
m.reply "illegal expression \"#{m.params}\""
return
end
end
end
plugin = MathPlugin.new
plugin.register("math")
|