Skip to content

Instantly share code, notes, and snippets.

@tompng
Last active December 14, 2015 04:59
Show Gist options
  • Save tompng/5031911 to your computer and use it in GitHub Desktop.
Save tompng/5031911 to your computer and use it in GitHub Desktop.
rubyの0.zero?を強くしてみた。 (five-thousand).minusninehundredninetyfive? && (twopointzero*314/onehundred).sixpointtwoeight? => true
class NumberParser
def self.parse(s)
match=->(str){
if s.start_with? str
s=s[str.length..-1]
true
end
}
find=->(arr){
key,value=arr.find{|x|s.start_with? x[0]}
if key
s=s[key.length..-1]
value
end
}
minus=match.call 'minus'
return nil if match.call 'and'
third_ninth=%w(thir four fif six seven eigh nine)
x9=%w(one two three four five six seven eight nine).zip(1..9)
x19=(%w(ten eleven twelve)+third_ninth.map{|x|x+'teen'}).zip(10..19)
x90=(['twenty']+third_ninth.map{|x|x+'ty'}).zip((2..9).map{|x|x*10})
find100=->{
val19=find.call(x19)
val19.nil? ? (find.call(x90)||0)+(find.call(x9)||0) : val19
}
find1000=->{
x=find100.call
if match.call 'hundred'
match.call 'and'
[1,x].max*100+find100.call
else
x
end
}
list=[['thousand',10**3],['million',10**6],['billion',10**9],['trillion',10**12]].reverse
value=0
if match.call 'zero'
return s.empty? ? 0 : nil unless match.call 'point'
else
loop do
if match.call 'and'
return nil if s.empty? or match.call 'and'
end
if match.call 'a'
return nil if s.empty? or match.call 'a'
end
x=find1000.call
return (minus ? -1 : 1)*(value+x) if s.empty?
return nil if x >= 1000
if match.call 'point'
return nil if s.empty?
value+=x
break
end
val=while not list.empty?
key,val=list.shift
break val if match.call key
end
return nil if val.nil?
value+=x==0?val:x*val
end
end
x10=[['zero',0]]+x9
digit=1
while not s.empty?
x=find.call x10
return nil if x.nil?
value=value*10+x
digit*=10
end
(minus ? -1 : 1)*value/digit.to_f
end
end
[Fixnum,Float].each{|c|
c.class_eval{
def method_missing name,*args
name.to_s.match /(?<number>[a-z]+)\?/ do |match|
num=NumberParser.parse match[:number]
return self==num unless num.nil?
end
super
end
}
}
def method_missing name
if name.to_s.match(/^[a-z]+$/) and num=NumberParser.parse(name.to_s)
num
else
super
end
end
p three
p threepointonefouronefiveninetwosixfivethreefiveeightninesevenninethree
p minusthirtytwothousandsevenhundredsixtyeightpointonezerothree
p 3.14.threepointonefour?
p 12.twelve?
p 1000.tenhundred?
p one+eleven+onehundredeleven
p 1000.athousand?
p -31.minusthirtyone?
p 1000413012.billionfourhundredthirteenthousandandtwelve?
p threehundredfiftyfive/hundredandthirteen.to_f
count=thousand
pi=onepointzero/count
count.times do |i|
pi+=fourpointzero*(one-i%two*two)/(one+two*i)
end
pi_true=threepointonefouronefiveninetwosixfivethreefiveeightninesevenninethree
print "pi=#{pi}\ndiff=#{pi-pi_true}\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment