зеркало из https://github.com/github/ruby.git
93 строки
1.6 KiB
Ruby
93 строки
1.6 KiB
Ruby
|
# The Great Computer Language Shootout
|
||
|
# http://shootout.alioth.debian.org/
|
||
|
#
|
||
|
# contributed by Gabriele Renzi
|
||
|
|
||
|
class PiDigitSpigot
|
||
|
|
||
|
def initialize()
|
||
|
@z = Transformation.new 1,0,0,1
|
||
|
@x = Transformation.new 0,0,0,0
|
||
|
@inverse = Transformation.new 0,0,0,0
|
||
|
end
|
||
|
|
||
|
def next!
|
||
|
@y = @z.extract(3)
|
||
|
if safe? @y
|
||
|
@z = produce(@y)
|
||
|
@y
|
||
|
else
|
||
|
@z = consume @x.next!()
|
||
|
next!()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def safe?(digit)
|
||
|
digit == @z.extract(4)
|
||
|
end
|
||
|
|
||
|
def produce(i)
|
||
|
@inverse.qrst(10,-10*i,0,1).compose(@z)
|
||
|
end
|
||
|
|
||
|
def consume(a)
|
||
|
@z.compose(a)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
class Transformation
|
||
|
attr_reader :q, :r, :s, :t
|
||
|
def initialize (q, r, s, t)
|
||
|
@q,@r,@s,@t,@k = q,r,s,t,0
|
||
|
end
|
||
|
|
||
|
def next!()
|
||
|
@q = @k = @k + 1
|
||
|
@r = 4 * @k + 2
|
||
|
@s = 0
|
||
|
@t = 2 * @k + 1
|
||
|
self
|
||
|
end
|
||
|
|
||
|
def extract(j)
|
||
|
(@q * j + @r) / (@s * j + @t)
|
||
|
end
|
||
|
|
||
|
def compose(a)
|
||
|
self.class.new( @q * a.q,
|
||
|
@q * a.r + r * a.t,
|
||
|
@s * a.q + t * a.s,
|
||
|
@s * a.r + t * a.t
|
||
|
)
|
||
|
end
|
||
|
|
||
|
def qrst *args
|
||
|
initialize *args
|
||
|
self
|
||
|
end
|
||
|
|
||
|
|
||
|
end
|
||
|
|
||
|
|
||
|
WIDTH = 10
|
||
|
n = 2_500 # Integer(ARGV[0])
|
||
|
j = 0
|
||
|
|
||
|
digits = PiDigitSpigot.new
|
||
|
|
||
|
while n > 0
|
||
|
if n >= WIDTH
|
||
|
WIDTH.times {print digits.next!}
|
||
|
j += WIDTH
|
||
|
else
|
||
|
n.times {print digits.next!}
|
||
|
(WIDTH-n).times {print " "}
|
||
|
j += n
|
||
|
end
|
||
|
puts "\t:"+j.to_s
|
||
|
n -= WIDTH
|
||
|
end
|
||
|
|