Last active
December 14, 2015 04:59
-
-
Save tompng/5031911 to your computer and use it in GitHub Desktop.
rubyの0.zero?を強くしてみた。
(five-thousand).minusninehundredninetyfive? && (twopointzero*314/onehundred).sixpointtwoeight?
=> true
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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