From: "M. Edward (Ed) Borasky" Date: 2007-12-26T03:38:46+09:00 Subject: Ruby 1.9.0-0 benchmarks This is a multi-part message in MIME format. --------------020808070108010307000003 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Here you go ... this is on my 4 GB dual-core Athlon64 X2 5200+ (2.2 GHz). The Ruby 1.8 is 1.8.6-p111 compiled with gcc 4.2.2 using "march=athlon64 -O2" and Ruby 1.9 was compiled with the same compiler but with flags "march=athlon64 -O3". I haven't re-run my other stuff (hemibel plots, jRuby, MatrixBenchmark, etc.) yet, mostly because I got my OLPC XO yesterday, a couple of weeks before I was expecting it. :) As I've noted before, I'm not planning to put Ruby 1.8 on it but will probably put 1.9.0-0 on it as soon as I get my cross-compiler process debugged. --------------020808070108010307000003 Content-Type: text/plain; name="benchmark.log" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="benchmark.log" ruby ../ruby-1.9.0-0/benchmark/driver.rb -v \ --executables="ruby; ./miniruby ../ruby-1.9.0-0/runruby.rb --extout=.ext --" \ --pattern='bm_' --directory=../ruby-1.9.0-0/benchmark "1.8.6" total: 68 trial(s) (1 trial(s) for 68 benchmark(s)) Tue Dec 25 09:35:25 -0800 2007 target 0: ruby 1.8.6 (2007-12-03) [x86_64-linux] target 1: ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] ----------------------------------------------------------- app_answer def ack(m, n) if m == 0 then n + 1 elsif n == 0 then ack(m - 1, 1) else ack(m - 1, ack(m, n - 1)) end end def the_answer_to_life_the_universe_and_everything (ack(3,7).to_s.split(//).inject(0){|s,x| s+x.to_i}.to_s + "2" ).to_i end answer = the_answer_to_life_the_universe_and_everything ruby 1.8.6 (2007-12-03) [x86_64-linux] .1.53625392913818 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.13400411605835 ----------------------------------------------------------- app_erb # # Create many HTML strings with ERB. # require 'erb' data = DATA.read max = 5_000 title = "hello world!" content = "hello world!\n" * 10 max.times{ ERB.new(data).result(binding) } __END__ <%= title %>

<%= title %>

<%= content %>

ruby 1.8.6 (2007-12-03) [x86_64-linux] .2.23458099365234 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.57998299598694 ----------------------------------------------------------- app_factorial def fact(n) if(n > 1) n * fact(n-1) else 1 end end 8.times{ fact(5000) } ruby 1.8.6 (2007-12-03) [x86_64-linux] .0.694716215133667 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.444912910461426 ----------------------------------------------------------- app_fib def fib n if n < 3 1 else fib(n-1) + fib(n-2) end end fib(34) ruby 1.8.6 (2007-12-03) [x86_64-linux] .11.3680670261383 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.44150710105896 ----------------------------------------------------------- app_mandelbrot require 'complex' def mandelbrot? z i = 0 while i<100 i+=1 z = z * z return false if z.abs > 2 end true end ary = [] (0..100).each{|dx| (0..100).each{|dy| x = dx / 50.0 y = dy / 50.0 c = Complex(x, y) ary << c if mandelbrot?(c) } } ruby 1.8.6 (2007-12-03) [x86_64-linux] .3.61981320381165 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.93461799621582 ----------------------------------------------------------- app_pentomino #!/usr/local/bin/ruby # This program is contributed by Shin Nishiyama # modified by K.Sasada NP = 5 ROW = 8 + NP COL = 8 $p = [] $b = [] $no = 0 def piece(n, a, nb) nb.each{|x| a[n] = x if n == NP-1 $p << [a.sort] else nbc=nb.dup [-ROW, -1, 1, ROW].each{|d| if x+d > 0 and not a.include?(x+d) and not nbc.include?(x+d) nbc << x+d end } nbc.delete x piece(n+1,a[0..n],nbc) end } end def kikaku(a) a.collect {|x| x - a[0]} end def ud(a) kikaku(a.collect {|x| ((x+NP)%ROW)-ROW*((x+NP)/ROW) }.sort) end def rl(a) kikaku(a.collect {|x| ROW*((x+NP)/ROW)+ROW-((x+NP)%ROW)}.sort) end def xy(a) kikaku(a.collect {|x| ROW*((x+NP)%ROW) + (x+NP)/ROW }.sort) end def mkpieces piece(0,[],[0]) $p.each do |a| a0 = a[0] a[1] = ud(a0) a[2] = rl(a0) a[3] = ud(rl(a0)) a[4] = xy(a0) a[5] = ud(xy(a0)) a[6] = rl(xy(a0)) a[7] = ud(rl(xy(a0))) a.sort! a.uniq! end $p.uniq!.sort! {|x,y| x[0] <=> y[0] } end def mkboard (0...ROW*COL).each{|i| if i % ROW >= ROW-NP $b[i] = -2 else $b[i] = -1 end $b[3*ROW+3]=$b[3*ROW+4]=$b[4*ROW+3]=$b[4*ROW+4]=-2 } end def pboard return # skip print print "No. #$no\n" (0...COL).each{|i| print "|" (0...ROW-NP).each{|j| x = $b[i*ROW+j] if x < 0 print "..|" else printf "%2d|",x+1 end } print "\n" } print "\n" end $pnum=[] def setpiece(a,pos) if a.length == $p.length then $no += 1 pboard return end while $b[pos] != -1 pos += 1 end ($pnum - a).each do |i| $p[i].each do |x| f = 0 x.each{|s| if $b[pos+s] != -1 f=1 break end } if f == 0 then x.each{|s| $b[pos+s] = i } a << i setpiece(a.dup, pos) a.pop x.each{|s| $b[pos+s] = -1 } end end end end mkpieces mkboard $p[4] = [$p[4][0]] $pnum = (0...$p.length).to_a setpiece([],0) __END__ # original NP = 5 ROW = 8 + NP COL = 8 $p = [] $b = [] $no = 0 def piece(n,a,nb) for x in nb a[n] = x if n == NP-1 $p << [a.sort] else nbc=nb.dup for d in [-ROW, -1, 1, ROW] if x+d > 0 and not a.include?(x+d) and not nbc.include?(x+d) nbc << x+d end end nbc.delete x piece(n+1,a[0..n],nbc) end end end def kikaku(a) a.collect {|x| x - a[0]} end def ud(a) kikaku(a.collect {|x| ((x+NP)%ROW)-ROW*((x+NP)/ROW) }.sort) end def rl(a) kikaku(a.collect {|x| ROW*((x+NP)/ROW)+ROW-((x+NP)%ROW)}.sort) end def xy(a) kikaku(a.collect {|x| ROW*((x+NP)%ROW) + (x+NP)/ROW }.sort) end def mkpieces piece(0,[],[0]) $p.each do |a| a0 = a[0] a[1] = ud(a0) a[2] = rl(a0) a[3] = ud(rl(a0)) a[4] = xy(a0) a[5] = ud(xy(a0)) a[6] = rl(xy(a0)) a[7] = ud(rl(xy(a0))) a.sort! a.uniq! end $p.uniq!.sort! {|x,y| x[0] <=> y[0] } end def mkboard for i in 0...ROW*COL if i % ROW >= ROW-NP $b[i] = -2 else $b[i] = -1 end $b[3*ROW+3]=$b[3*ROW+4]=$b[4*ROW+3]=$b[4*ROW+4]=-2 end end def pboard print "No. #$no\n" for i in 0...COL print "|" for j in 0...ROW-NP x = $b[i*ROW+j] if x < 0 print "..|" else printf "%2d|",x+1 end end print "\n" end print "\n" end $pnum=[] def setpiece(a,pos) if a.length == $p.length then $no += 1 pboard return end while $b[pos] != -1 pos += 1 end ($pnum - a).each do |i| $p[i].each do |x| f = 0 for s in x do if $b[pos+s] != -1 f=1 break end end if f == 0 then for s in x do $b[pos+s] = i end a << i setpiece(a.dup, pos) a.pop for s in x do $b[pos+s] = -1 end end end end end mkpieces mkboard $p[4] = [$p[4][0]] $pnum = (0...$p.length).to_a setpiece([],0) ruby 1.8.6 (2007-12-03) [x86_64-linux] .183.978760957718 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .39.9713780879974 ----------------------------------------------------------- app_raise i=0 while i<300000 i+=1 begin raise rescue end end ruby 1.8.6 (2007-12-03) [x86_64-linux] .1.69808006286621 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.68952989578247 ----------------------------------------------------------- app_strconcat i=0 while i<500000 "#{1+1} #{1+1} #{1+1}" i+=1 end ruby 1.8.6 (2007-12-03) [x86_64-linux] .1.57846403121948 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.996259927749634 ----------------------------------------------------------- app_tak def tak x, y, z unless y < x z else tak( tak(x-1, y, z), tak(y-1, z, x), tak(z-1, x, y)) end end tak(18, 9, 0) ruby 1.8.6 (2007-12-03) [x86_64-linux] .14.9776599407196 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .2.18618512153625 ----------------------------------------------------------- app_tarai def tarai( x, y, z ) if x <= y then y else tarai(tarai(x-1, y, z), tarai(y-1, z, x), tarai(z-1, x, y)) end end tarai(12, 6, 0) ruby 1.8.6 (2007-12-03) [x86_64-linux] .12.5582439899445 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.79245805740356 ----------------------------------------------------------- app_uri require 'uri' 100_000.times{ uri = URI.parse('http://www.ruby-lang.org') uri.scheme uri.host uri.port } ruby 1.8.6 (2007-12-03) [x86_64-linux] .4.96692991256714 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.98099994659424 ----------------------------------------------------------- io_file_create # # Create files # max = 50_000 file = './tmpfile_of_bm_io_file_create' max.times{ f = open(file, 'w') f.close#(true) } File.unlink(file) ruby 1.8.6 (2007-12-03) [x86_64-linux] .0.550206899642944 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.566741943359375 ----------------------------------------------------------- io_file_read # # Seek and Read file. # require 'tempfile' max = 20_000 str = "Hello world! " * 1000 f = Tempfile.new('yarv-benchmark') f.write str max.times{ f.seek 0 f.read } ruby 1.8.6 (2007-12-03) [x86_64-linux] .0.72334885597229 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.519173860549927 ----------------------------------------------------------- io_file_write # # Seek and Write file. # require 'tempfile' max = 20_000 str = "Hello world! " * 1000 f = Tempfile.new('yarv-benchmark') max.times{ f.seek 0 f.write str } ruby 1.8.6 (2007-12-03) [x86_64-linux] .0.356566905975342 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.262768983840942 ----------------------------------------------------------- loop_generator max = 600000 if defined? Fiber gen = (1..max).each loop do gen.next end else require 'generator' gen = Generator.new((0..max)) while gen.next? gen.next end end ruby 1.8.6 (2007-12-03) [x86_64-linux] .56.5723481178284 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.11044692993164 ----------------------------------------------------------- loop_times 30000000.times{|e|} ruby 1.8.6 (2007-12-03) [x86_64-linux] .11.2022171020508 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .2.43959283828735 ----------------------------------------------------------- loop_whileloop i=0 while i<30_000_000 # benchmark loop 1 i+=1 end ruby 1.8.6 (2007-12-03) [x86_64-linux] .13.0046269893646 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.45603704452515 ----------------------------------------------------------- loop_whileloop2 i=0 while i< 6_000_000 # benchmark loop 2 i+=1 end ruby 1.8.6 (2007-12-03) [x86_64-linux] .2.50535702705383 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.320430040359497 ----------------------------------------------------------- so_ackermann #!/usr/bin/ruby # -*- mode: ruby -*- # $Id: ackermann-ruby.code,v 1.4 2004/11/13 07:40:41 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ def ack(m, n) if m == 0 then n + 1 elsif n == 0 then ack(m - 1, 1) else ack(m - 1, ack(m, n - 1)) end end NUM = 9 ack(3, NUM) ruby 1.8.6 (2007-12-03) [x86_64-linux] .26.2885670661926 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.85544490814209 ----------------------------------------------------------- so_array #!/usr/bin/ruby # -*- mode: ruby -*- # $Id: ary-ruby.code,v 1.4 2004/11/13 07:41:27 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ # with help from Paul Brannan and Mark Hubbart n = 9000 # Integer(ARGV.shift || 1) x = Array.new(n) y = Array.new(n, 0) n.times{|bi| x[bi] = bi + 1 } (0 .. 999).each do |e| (n-1).step(0,-1) do |bi| y[bi] += x.at(bi) end end # puts "#{y.first} #{y.last}" ruby 1.8.6 (2007-12-03) [x86_64-linux] .11.4453599452972 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .2.67545294761658 ----------------------------------------------------------- so_binary_trees # The Computer Language Shootout Benchmarks # http://shootout.alioth.debian.org # # contributed by Jesse Millikan # disable output def STDOUT.write_ *args end def item_check(tree) if tree[0] == nil tree[1] else tree[1] + item_check(tree[0]) - item_check(tree[2]) end end def bottom_up_tree(item, depth) if depth > 0 item_item = 2 * item depth -= 1 [bottom_up_tree(item_item - 1, depth), item, bottom_up_tree(item_item, depth)] else [nil, item, nil] end end max_depth = 12 # 16 # ARGV[0].to_i min_depth = 4 max_depth = min_depth + 2 if min_depth + 2 > max_depth stretch_depth = max_depth + 1 stretch_tree = bottom_up_tree(0, stretch_depth) puts "stretch tree of depth #{stretch_depth}\t check: #{item_check(stretch_tree)}" stretch_tree = nil long_lived_tree = bottom_up_tree(0, max_depth) min_depth.step(max_depth + 1, 2) do |depth| iterations = 2**(max_depth - depth + min_depth) check = 0 for i in 1..iterations temp_tree = bottom_up_tree(i, depth) check += item_check(temp_tree) temp_tree = bottom_up_tree(-i, depth) check += item_check(temp_tree) end puts "#{iterations * 2}\t trees of depth #{depth}\t check: #{check}" end puts "long lived tree of depth #{max_depth}\t check: #{item_check(long_lived_tree)}" ruby 1.8.6 (2007-12-03) [x86_64-linux] .4.30503797531128 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.36704993247986 ----------------------------------------------------------- so_concatenate #!/usr/bin/ruby # -*- mode: ruby -*- # $Id: strcat-ruby.code,v 1.4 2004/11/13 07:43:28 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ # based on code from Aristarkh A Zagorodnikov and Dat Nguyen STUFF = "hello\n" i=0 while i<10 i+=1 hello = '' 400000.times do |e| hello << STUFF end end # puts hello.length ruby 1.8.6 (2007-12-03) [x86_64-linux] .3.91674900054932 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.882771968841553 ----------------------------------------------------------- so_count_words #!/usr/bin/ruby # -*- mode: ruby -*- # $Id: wc-ruby.code,v 1.4 2004/11/13 07:43:32 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ # with help from Paul Brannan input = open(File.join(File.dirname($0), 'wc.input'), 'rb') nl = nw = nc = 0 while true tmp = input.read(4096) or break data = tmp << (input.gets || "") nc += data.length nl += data.count("\n") ((data.strip! || data).tr!("\n", " ") || data).squeeze! nw += data.count(" ") + 1 end # STDERR.puts "#{nl} #{nw} #{nc}" ruby 1.8.6 (2007-12-03) [x86_64-linux] .0.490777969360352 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .3.55722904205322 ----------------------------------------------------------- so_exception #!/usr/bin/ruby # -*- mode: ruby -*- # $Id: except-ruby.code,v 1.4 2004/11/13 07:41:33 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ $HI = 0 $LO = 0 NUM = 250000 # Integer(ARGV[0] || 1) class Lo_Exception < Exception def initialize(num) @value = num end end class Hi_Exception < Exception def initialize(num) @value = num end end def some_function(num) begin hi_function(num) rescue print "We shouldn't get here, exception is: #{$!.type}\n" end end def hi_function(num) begin lo_function(num) rescue Hi_Exception $HI = $HI + 1 end end def lo_function(num) begin blowup(num) rescue Lo_Exception $LO = $LO + 1 end end def blowup(num) if num % 2 == 0 raise Lo_Exception.new(num) else raise Hi_Exception.new(num) end end i = 1 max = NUM+1 while i < max i+=1 some_function(i+1) end ruby 1.8.6 (2007-12-03) [x86_64-linux] .3.67201900482178 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .2.55055713653564 ----------------------------------------------------------- so_fannkuch # The Computer Language Shootout # http://shootout.alioth.debian.org/ # Contributed by Sokolov Yura # Modified by Ryan Williams def fannkuch(n) maxFlips, m, r, check = 0, n-1, n, 0 count = (1..n).to_a perm = (1..n).to_a while true if check < 30 puts "#{perm}" check += 1 end while r != 1 count[r-1] = r r -= 1 end if perm[0] != 1 and perm[m] != n perml = perm.clone #.dup flips = 0 while (k = perml.first ) != 1 perml = perml.slice!(0, k).reverse + perml flips += 1 end maxFlips = flips if flips > maxFlips end while true if r==n then return maxFlips end perm.insert r,perm.shift break if (count[r] -= 1) > 0 r += 1 end end end def puts *args end N = 10 # (ARGV[0] || 1).to_i puts "Pfannkuchen(#{N}) = #{fannkuch(N)}" ruby 1.8.6 (2007-12-03) [x86_64-linux] .84.7616000175476 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .51.860946893692 ----------------------------------------------------------- so_fasta # The Computer Language Shootout # http://shootout.alioth.debian.org/ # Contributed by Sokolov Yura $last = 42.0 def gen_random (max,im=139968,ia=3877,ic=29573) (max * ($last = ($last * ia + ic) % im)) / im end alu = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG"+ "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA"+ "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT"+ "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA"+ "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG"+ "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC"+ "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA" iub = [ ["a", 0.27], ["c", 0.12], ["g", 0.12], ["t", 0.27], ["B", 0.02], ["D", 0.02], ["H", 0.02], ["K", 0.02], ["M", 0.02], ["N", 0.02], ["R", 0.02], ["S", 0.02], ["V", 0.02], ["W", 0.02], ["Y", 0.02], ] homosapiens = [ ["a", 0.3029549426680], ["c", 0.1979883004921], ["g", 0.1975473066391], ["t", 0.3015094502008], ] def make_repeat_fasta(id, desc, src, n) puts ">#{id} #{desc}" v = nil width = 60 l = src.length s = src * ((n / l) + 1) s.slice!(n, l) puts(s.scan(/.{1,#{width}}/).join("\n")) end def make_random_fasta(id, desc, table, n) puts ">#{id} #{desc}" rand, v = nil,nil width = 60 chunk = 1 * width prob = 0.0 table.each{|v| v[1]= (prob += v[1])} for i in 1..(n/width) puts((1..width).collect{ rand = gen_random(1.0) table.find{|v| v[1]>rand}[0] }.join) end if n%width != 0 puts((1..(n%width)).collect{ rand = gen_random(1.0) table.find{|v| v[1]>rand}[0] }.join) end end n = (ARGV[0] or 250_000).to_i make_repeat_fasta('ONE', 'Homo sapiens alu', alu, n*2) make_random_fasta('TWO', 'IUB ambiguity codes', iub, n*3) make_random_fasta('THREE', 'Homo sapiens frequency', homosapiens, n*5) ruby 1.8.6 (2007-12-03) [x86_64-linux] .19.389740228653 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .preparing ../ruby-1.9.0-0/benchmark/fasta.output.100000 5.67655801773071 ----------------------------------------------------------- so_k_nucleotide # The Computer Language Shootout # http://shootout.alioth.debian.org # # contributed by jose fco. gonzalez # modified by Sokolov Yura seq = String.new def frecuency( seq,length ) n, table = seq.length - length + 1, Hash.new(0) f, i = nil, nil (0 ... length).each do |f| (f ... n).step(length) do |i| table[seq[i,length]] += 1 end end [n,table] end def sort_by_freq( seq,length ) n,table = frecuency( seq,length ) a, b, v = nil, nil, nil table.sort{|a,b| b[1] <=> a[1]}.each do |v| puts "%s %.3f" % [v[0].upcase,((v[1]*100).to_f/n)] end puts end def find_seq( seq,s ) n,table = frecuency( seq,s.length ) puts "#{table[s].to_s}\t#{s.upcase}" end input = open(File.join(File.dirname($0), 'fasta.output.100000'), 'rb') line = input.gets while line !~ /^>THREE/ line = input.gets while (line !~ /^>/) & line do seq << line.chomp line = input.gets end [1,2].each {|i| sort_by_freq( seq,i ) } %w(ggt ggta ggtatt ggtattttaatt ggtattttaatttatagt).each{|s| find_seq( seq,s) } ruby 1.8.6 (2007-12-03) [x86_64-linux] .8.10035991668701 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .4.2192759513855 ----------------------------------------------------------- so_lists #from http://www.bagley.org/~doug/shootout/bench/lists/lists.ruby NUM = 100 SIZE = 10000 def test_lists() # create a list of integers (Li1) from 1 to SIZE li1 = (1..SIZE).to_a # copy the list to li2 (not by individual items) li2 = li1.dup # remove each individual item from left side of li2 and # append to right side of li3 (preserving order) li3 = Array.new while (not li2.empty?) li3.push(li2.shift) end # li2 must now be empty # remove each individual item from right side of li3 and # append to right side of li2 (reversing list) while (not li3.empty?) li2.push(li3.pop) end # li3 must now be empty # reverse li1 in place li1.reverse! # check that first item is now SIZE if li1[0] != SIZE then p "not SIZE" 0 else # compare li1 and li2 for equality if li1 != li2 then return(0) else # return the length of the list li1.length end end end i = 0 while i LIMIT_SQUARED escape = true break end end byte_acc = (byte_acc << 1) | (escape ? 0b0 : 0b1) bit_num += 1 # Code is very similar for these cases, but using separate blocks # ensures we skip the shifting when it's unnecessary, which is most cases. if (bit_num == 8) print byte_acc.chr byte_acc = 0 bit_num = 0 elsif (x == count_size) byte_acc <<= (8 - bit_num) print byte_acc.chr byte_acc = 0 bit_num = 0 end end end ruby 1.8.6 (2007-12-03) [x86_64-linux] .42.8019068241119 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .16.2084069252014 ----------------------------------------------------------- so_matrix #!/usr/bin/ruby # -*- mode: ruby -*- # $Id: matrix-ruby.code,v 1.4 2004/11/13 07:42:14 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ n = 60 #Integer(ARGV.shift || 1) size = 30 def mkmatrix(rows, cols) count = 1 mx = Array.new(rows) (0 .. (rows - 1)).each do |bi| row = Array.new(cols, 0) (0 .. (cols - 1)).each do |j| row[j] = count count += 1 end mx[bi] = row end mx end def mmult(rows, cols, m1, m2) m3 = Array.new(rows) (0 .. (rows - 1)).each do |bi| row = Array.new(cols, 0) (0 .. (cols - 1)).each do |j| val = 0 (0 .. (cols - 1)).each do |k| val += m1.at(bi).at(k) * m2.at(k).at(j) end row[j] = val end m3[bi] = row end m3 end m1 = mkmatrix(size, size) m2 = mkmatrix(size, size) mm = Array.new n.times do mm = mmult(size, size, m1, m2) end # puts "#{mm[0][0]} #{mm[2][3]} #{mm[3][2]} #{mm[4][4]}" ruby 1.8.6 (2007-12-03) [x86_64-linux] .3.27859997749329 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.793742179870605 ----------------------------------------------------------- so_meteor_contest #!/usr/bin/env ruby # # The Computer Language Shootout # http://shootout.alioth.debian.org # contributed by Kevin Barnes (Ruby novice) # PROGRAM: the main body is at the bottom. # 1) read about the problem here: http://www-128.ibm.com/developerworks/java/library/j-javaopt/ # 2) see how I represent a board as a bitmask by reading the blank_board comments # 3) read as your mental paths take you def print *args end # class to represent all information about a particular rotation of a particular piece class Rotation # an array (by location) containing a bit mask for how the piece maps at the given location. # if the rotation is invalid at that location the mask will contain false attr_reader :start_masks # maps a direction to a relative location. these differ depending on whether it is an even or # odd row being mapped from @@rotation_even_adder = { :west => -1, :east => 1, :nw => -7, :ne => -6, :sw => 5, :se => 6 } @@rotation_odd_adder = { :west => -1, :east => 1, :nw => -6, :ne => -5, :sw => 6, :se => 7 } def initialize( directions ) @even_offsets, @odd_offsets = normalize_offsets( get_values( directions )) @even_mask = mask_for_offsets( @even_offsets) @odd_mask = mask_for_offsets( @odd_offsets) @start_masks = Array.new(60) # create the rotational masks by placing the base mask at the location and seeing if # 1) it overlaps the boundries and 2) it produces a prunable board. if either of these # is true the piece cannot be placed 0.upto(59) do | offset | mask = is_even(offset) ? (@even_mask << offset) : (@odd_mask << offset) if (blank_board & mask == 0 && !prunable(blank_board | mask, 0, true)) then imask = compute_required( mask, offset) @start_masks[offset] = [ mask, imask, imask | mask ] else @start_masks[offset] = false end end end def compute_required( mask, offset ) board = blank_board 0.upto(offset) { | i | board |= 1 << i } board |= mask return 0 if (!prunable(board | mask, offset)) board = flood_fill(board,58) count = 0 imask = 0 0.upto(59) do | i | if (board[i] == 0) then imask |= (1 << i) count += 1 end end (count > 0 && count < 5) ? imask : 0 end def flood_fill( board, location) return board if (board[location] == 1) board |= 1 << location row, col = location.divmod(6) board = flood_fill( board, location - 1) if (col > 0) board = flood_fill( board, location + 1) if (col < 4) if (row % 2 == 0) then board = flood_fill( board, location - 7) if (col > 0 && row > 0) board = flood_fill( board, location - 6) if (row > 0) board = flood_fill( board, location + 6) if (row < 9) board = flood_fill( board, location + 5) if (col > 0 && row < 9) else board = flood_fill( board, location - 5) if (col < 4 && row > 0) board = flood_fill( board, location - 6) if (row > 0) board = flood_fill( board, location + 6) if (row < 9) board = flood_fill( board, location + 7) if (col < 4 && row < 9) end board end # given a location, produces a list of relative locations covered by the piece at this rotation def offsets( location) if is_even( location) then @even_offsets.collect { | value | value + location } else @odd_offsets.collect { | value | value + location } end end # returns a set of offsets relative to the top-left most piece of the rotation (by even or odd rows) # this is hard to explain. imagine we have this partial board: # 0 0 0 0 0 x [positions 0-5] # 0 0 1 1 0 x [positions 6-11] # 0 0 1 0 0 x [positions 12-17] # 0 1 0 0 0 x [positions 18-23] # 0 1 0 0 0 x [positions 24-29] # 0 0 0 0 0 x [positions 30-35] # ... # The top-left of the piece is at position 8, the # board would be passed as a set of positions (values array) containing [8,9,14,19,25] not necessarily in that # sorted order. Since that array starts on an odd row, the offsets for an odd row are: [0,1,6,11,17] obtained # by subtracting 8 from everything. Now imagine the piece shifted up and to the right so it's on an even row: # 0 0 0 1 1 x [positions 0-5] # 0 0 1 0 0 x [positions 6-11] # 0 0 1 0 0 x [positions 12-17] # 0 1 0 0 0 x [positions 18-23] # 0 0 0 0 0 x [positions 24-29] # 0 0 0 0 0 x [positions 30-35] # ... # Now the positions are [3,4,8,14,19] which after subtracting the lowest value (3) gives [0,1,5,11,16] thus, the # offsets for this particular piece are (in even, odd order) [0,1,5,11,16],[0,1,6,11,17] which is what # this function would return def normalize_offsets( values) min = values.min even_min = is_even(min) other_min = even_min ? min + 6 : min + 7 other_values = values.collect do | value | if is_even(value) then value + 6 - other_min else value + 7 - other_min end end values.collect! { | value | value - min } if even_min then [values, other_values] else [other_values, values] end end # produce a bitmask representation of an array of offset locations def mask_for_offsets( offsets ) mask = 0 offsets.each { | value | mask = mask + ( 1 << value ) } mask end # finds a "safe" position that a position as described by a list of directions can be placed # without falling off any edge of the board. the values returned a location to place the first piece # at so it will fit after making the described moves def start_adjust( directions ) south = east = 0; directions.each do | direction | east += 1 if ( direction == :sw || direction == :nw || direction == :west ) south += 1 if ( direction == :nw || direction == :ne ) end south * 6 + east end # given a set of directions places the piece (as defined by a set of directions) on the board at # a location that will not take it off the edge def get_values ( directions ) start = start_adjust(directions) values = [ start ] directions.each do | direction | if (start % 12 >= 6) then start += @@rotation_odd_adder[direction] else start += @@rotation_even_adder[direction] end values += [ start ] end # some moves take you back to an existing location, we'll strip duplicates values.uniq end end # describes a piece and caches information about its rotations to as to be efficient for iteration # ATTRIBUTES: # rotations -- all the rotations of the piece # type -- a numeic "name" of the piece # masks -- an array by location of all legal rotational masks (a n inner array) for that location # placed -- the mask that this piece was last placed at (not a location, but the actual mask used) class Piece attr_reader :rotations, :type, :masks attr_accessor :placed # transform hashes that change one direction into another when you either flip or rotate a set of directions @@flip_converter = { :west => :west, :east => :east, :nw => :sw, :ne => :se, :sw => :nw, :se => :ne } @@rotate_converter = { :west => :nw, :east => :se, :nw => :ne, :ne => :east, :sw => :west, :se => :sw } def initialize( directions, type ) @type = type @rotations = Array.new(); @map = {} generate_rotations( directions ) directions.collect! { | value | @@flip_converter[value] } generate_rotations( directions ) # creates the masks AND a map that returns [location, rotation] for any given mask # this is used when a board is found and we want to draw it, otherwise the map is unused @masks = Array.new(); 0.upto(59) do | i | even = true @masks[i] = @rotations.collect do | rotation | mask = rotation.start_masks[i] @map[mask[0]] = [ i, rotation ] if (mask) mask || nil end @masks[i].compact! end end # rotates a set of directions through all six angles and adds a Rotation to the list for each one def generate_rotations( directions ) 6.times do rotations.push( Rotation.new(directions)) directions.collect! { | value | @@rotate_converter[value] } end end # given a board string, adds this piece to the board at whatever location/rotation # important: the outbound board string is 5 wide, the normal location notation is six wide (padded) def fill_string( board_string) location, rotation = @map[@placed] rotation.offsets(location).each do | offset | row, col = offset.divmod(6) board_string[ row*5 + col, 1 ] = @type.to_s end end end # a blank bit board having this form: # # 0 0 0 0 0 1 # 0 0 0 0 0 1 # 0 0 0 0 0 1 # 0 0 0 0 0 1 # 0 0 0 0 0 1 # 0 0 0 0 0 1 # 0 0 0 0 0 1 # 0 0 0 0 0 1 # 0 0 0 0 0 1 # 0 0 0 0 0 1 # 1 1 1 1 1 1 # # where left lest significant bit is the top left and the most significant is the lower right # the actual board only consists of the 0 places, the 1 places are blockers to keep things from running # off the edges or bottom def blank_board 0b111111100000100000100000100000100000100000100000100000100000100000 end def full_board 0b111111111111111111111111111111111111111111111111111111111111111111 end # determines if a location (bit position) is in an even row def is_even( location) (location % 12) < 6 end # support function that create three utility maps: # $converter -- for each row an array that maps a five bit row (via array mapping) # to the a a five bit representation of the bits below it # $bit_count -- maps a five bit row (via array mapping) to the number of 1s in the row # @@new_regions -- maps a five bit row (via array mapping) to an array of "region" arrays # a region array has three values the first is a mask of bits in the region, # the second is the count of those bits and the third is identical to the first # examples: # 0b10010 => [ 0b01100, 2, 0b01100 ], [ 0b00001, 1, 0b00001] # 0b01010 => [ 0b10000, 1, 0b10000 ], [ 0b00100, 1, 0b00100 ], [ 0b00001, 1, 0b00001] # 0b10001 => [ 0b01110, 3, 0b01110 ] def create_collector_support odd_map = [0b11, 0b110, 0b1100, 0b11000, 0b10000] even_map = [0b1, 0b11, 0b110, 0b1100, 0b11000] all_odds = Array.new(0b100000) all_evens = Array.new(0b100000) bit_counts = Array.new(0b100000) new_regions = Array.new(0b100000) 0.upto(0b11111) do | i | bit_count = odd = even = 0 0.upto(4) do | bit | if (i[bit] == 1) then bit_count += 1 odd |= odd_map[bit] even |= even_map[bit] end end all_odds[i] = odd all_evens[i] = even bit_counts[i] = bit_count new_regions[i] = create_regions( i) end $converter = [] 10.times { | row | $converter.push((row % 2 == 0) ? all_evens : all_odds) } $bit_counts = bit_counts $regions = new_regions.collect { | set | set.collect { | value | [ value, bit_counts[value], value] } } end # determines if a board is punable, meaning that there is no possibility that it # can be filled up with pieces. A board is prunable if there is a grouping of unfilled spaces # that are not a multiple of five. The following board is an example of a prunable board: # 0 0 1 0 0 # 0 1 0 0 0 # 1 1 0 0 0 # 0 1 0 0 0 # 0 0 0 0 0 # ... # # This board is prunable because the top left corner is only 3 bits in area, no piece will ever fit it # parameters: # board -- an initial bit board (6 bit padded rows, see blank_board for format) # location -- starting location, everything above and to the left is already full # slotting -- set to true only when testing initial pieces, when filling normally # additional assumptions are possible # # Algorithm: # The algorithm starts at the top row (as determined by location) and iterates a row at a time # maintainng counts of active open areas (kept in the collector array) each collector contains # three values at the start of an iteration: # 0: mask of bits that would be adjacent to the collector in this row # 1: the number of bits collected so far # 2: a scratch space starting as zero, but used during the computation to represent # the empty bits in the new row that are adjacent (position 0) # The exact procedure is described in-code def prunable( board, location, slotting = false) collectors = [] # loop accross the rows (location / 6).to_i.upto(9) do | row_on | # obtain a set of regions representing the bits of the curent row. regions = $regions[(board >> (row_on * 6)) & 0b11111] converter = $converter[row_on] # track the number of collectors at the start of the cycle so that # we don't compute against newly created collectors, only existing collectors initial_collector_count = collectors.length # loop against the regions. For each region of the row # we will see if it connects to one or more existing collectors. # if it connects to 1 collector, the bits from the region are added to the # bits of the collector and the mask is placed in collector[2] # If the region overlaps more than one collector then all the collectors # it overlaps with are merged into the first one (the others are set to nil in the array) # if NO collectors are found then the region is copied as a new collector regions.each do | region | collector_found = nil region_mask = region[2] initial_collector_count.times do | collector_num | collector = collectors[collector_num] if (collector) then collector_mask = collector[0] if (collector_mask & region_mask != 0) then if (collector_found) then collector_found[0] |= collector_mask collector_found[1] += collector[1] collector_found[2] |= collector[2] collectors[collector_num] = nil else collector_found = collector collector[1] += region[1] collector[2] |= region_mask end end end end if (collector_found == nil) then collectors.push(Array.new(region)) end end # check the existing collectors, if any collector overlapped no bits in the region its [2] value will # be zero. The size of any such reaason is tested if it is not a muliple of five true is returned since # the board is prunable. if it is a multiple of five it is removed. # Collector that are still active have a new adjacent value [0] set based n the matched bits # and have [2] cleared out for the next cycle. collectors.length.times do | collector_num | collector = collectors[collector_num] if (collector) then if (collector[2] == 0) then return true if (collector[1] % 5 != 0) collectors[collector_num] = nil else # if a collector matches all bits in the row then we can return unprunable early for the # follwing reasons: # 1) there can be no more unavailable bits bince we fill from the top left downward # 2) all previous regions have been closed or joined so only this region can fail # 3) this region must be good since there can never be only 1 region that is nuot # a multiple of five # this rule only applies when filling normally, so we ignore the rule if we are "slotting" # in pieces to see what configurations work for them (the only other time this algorithm is used). return false if (collector[2] == 0b11111 && !slotting) collector[0] = converter[collector[2]] collector[2] = 0 end end end # get rid of all the empty converters for the next round collectors.compact! end return false if (collectors.length <= 1) # 1 collector or less and the region is fine collectors.any? { | collector | (collector[1] % 5) != 0 } # more than 1 and we test them all for bad size end # creates a region given a row mask. see prunable for what a "region" is def create_regions( value ) regions = [] cur_region = 0 5.times do | bit | if (value[bit] == 0) then cur_region |= 1 << bit else if (cur_region != 0 ) then regions.push( cur_region) cur_region = 0; end end end regions.push(cur_region) if (cur_region != 0) regions end # find up to the counted number of solutions (or all solutions) and prints the final result def find_all find_top( 1) find_top( 0) print_results end # show the board def print_results print "#{@boards_found} solutions found\n\n" print_full_board( @min_board) print "\n" print_full_board( @max_board) print "\n" end # finds solutions. This special version of the main function is only used for the top level # the reason for it is basically to force a particular ordering on how the rotations are tested for # the first piece. It is called twice, first looking for placements of the odd rotations and then # looking for placements of the even locations. # # WHY? # Since any found solution has an inverse we want to maximize finding solutions that are not already found # as an inverse. The inverse will ALWAYS be 3 one of the piece configurations that is exactly 3 rotations away # (an odd number). Checking even vs odd then produces a higher probability of finding more pieces earlier # in the cycle. We still need to keep checking all the permutations, but our probability of finding one will # diminsh over time. Since we are TOLD how many to search for this lets us exit before checking all pieces # this bennifit is very great when seeking small numbers of solutions and is 0 when looking for more than the # maximum number def find_top( rotation_skip) board = blank_board (@pieces.length-1).times do piece = @pieces.shift piece.masks[0].each do | mask, imask, cmask | if ((rotation_skip += 1) % 2 == 0) then piece.placed = mask find( 1, 1, board | mask) end end @pieces.push(piece) end piece = @pieces.shift @pieces.push(piece) end # the normail find routine, iterates through the available pieces, checks all rotations at the current location # and adds any boards found. depth is acheived via recursion. the overall approach is described # here: http://www-128.ibm.com/developerworks/java/library/j-javaopt/ # parameters: # start_location -- where to start looking for place for the next piece at # placed -- number of pieces placed # board -- current state of the board # # see in-code comments def find( start_location, placed, board) # find the next location to place a piece by looking for an empty bit while board[start_location] == 1 start_location += 1 end @pieces.length.times do piece = @pieces.shift piece.masks[start_location].each do | mask, imask, cmask | if ( board & cmask == imask) then piece.placed = mask if (placed == 9) then add_board else find( start_location + 1, placed + 1, board | mask) end end end @pieces.push(piece) end end # print the board def print_full_board( board_string) 10.times do | row | print " " if (row % 2 == 1) 5.times do | col | print "#{board_string[row*5 + col,1]} " end print "\n" end end # when a board is found we "draw it" into a string and then flip that string, adding both to # the list (hash) of solutions if they are unique. def add_board board_string = "99999999999999999999999999999999999999999999999999" @all_pieces.each { | piece | piece.fill_string( board_string ) } save( board_string) save( board_string.reverse) end # adds a board string to the list (if new) and updates the current best/worst board def save( board_string) if (@all_boards[board_string] == nil) then @min_board = board_string if (board_string < @min_board) @max_board = board_string if (board_string > @max_board) @all_boards.store(board_string,true) @boards_found += 1 # the exit motif is a time saver. Ideally the function should return, but those tests # take noticable time (performance). if (@boards_found == @stop_count) then print_results exit(0) end end end ## ## MAIN BODY :) ## create_collector_support @pieces = [ Piece.new( [ :nw, :ne, :east, :east ], 2), Piece.new( [ :ne, :se, :east, :ne ], 7), Piece.new( [ :ne, :east, :ne, :nw ], 1), Piece.new( [ :east, :sw, :sw, :se ], 6), Piece.new( [ :east, :ne, :se, :ne ], 5), Piece.new( [ :east, :east, :east, :se ], 0), Piece.new( [ :ne, :nw, :se, :east, :se ], 4), Piece.new( [ :se, :se, :se, :west ], 9), Piece.new( [ :se, :se, :east, :se ], 8), Piece.new( [ :east, :east, :sw, :se ], 3) ]; @all_pieces = Array.new( @pieces) @min_board = "99999999999999999999999999999999999999999999999999" @max_board = "00000000000000000000000000000000000000000000000000" @stop_count = ARGV[0].to_i || 2089 @all_boards = {} @boards_found = 0 find_all ######## DO IT!!! ruby 1.8.6 (2007-12-03) [x86_64-linux] .52.2575500011444 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .20.0999820232391 ----------------------------------------------------------- so_nbody # The Computer Language Shootout # http://shootout.alioth.debian.org # # Optimized for Ruby by Jesse Millikan # From version ported by Michael Neumann from the C gcc version, # which was written by Christoph Bauer. SOLAR_MASS = 4 * Math::PI**2 DAYS_PER_YEAR = 365.24 def _puts *args end class Planet attr_accessor :x, :y, :z, :vx, :vy, :vz, :mass def initialize(x, y, z, vx, vy, vz, mass) @x, @y, @z = x, y, z @vx, @vy, @vz = vx * DAYS_PER_YEAR, vy * DAYS_PER_YEAR, vz * DAYS_PER_YEAR @mass = mass * SOLAR_MASS end def move_from_i(bodies, nbodies, dt, i) while i < nbodies b2 = bodies[i] dx = @x - b2.x dy = @y - b2.y dz = @z - b2.z distance = Math.sqrt(dx * dx + dy * dy + dz * dz) mag = dt / (distance * distance * distance) b_mass_mag, b2_mass_mag = @mass * mag, b2.mass * mag @vx -= dx * b2_mass_mag @vy -= dy * b2_mass_mag @vz -= dz * b2_mass_mag b2.vx += dx * b_mass_mag b2.vy += dy * b_mass_mag b2.vz += dz * b_mass_mag i += 1 end @x += dt * @vx @y += dt * @vy @z += dt * @vz end end def energy(bodies) e = 0.0 nbodies = bodies.size for i in 0 ... nbodies b = bodies[i] e += 0.5 * b.mass * (b.vx * b.vx + b.vy * b.vy + b.vz * b.vz) for j in (i + 1) ... nbodies b2 = bodies[j] dx = b.x - b2.x dy = b.y - b2.y dz = b.z - b2.z distance = Math.sqrt(dx * dx + dy * dy + dz * dz) e -= (b.mass * b2.mass) / distance end end e end def offset_momentum(bodies) px, py, pz = 0.0, 0.0, 0.0 for b in bodies m = b.mass px += b.vx * m py += b.vy * m pz += b.vz * m end b = bodies[0] b.vx = - px / SOLAR_MASS b.vy = - py / SOLAR_MASS b.vz = - pz / SOLAR_MASS end BODIES = [ # sun Planet.new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0), # jupiter Planet.new( 4.84143144246472090e+00, -1.16032004402742839e+00, -1.03622044471123109e-01, 1.66007664274403694e-03, 7.69901118419740425e-03, -6.90460016972063023e-05, 9.54791938424326609e-04), # saturn Planet.new( 8.34336671824457987e+00, 4.12479856412430479e+00, -4.03523417114321381e-01, -2.76742510726862411e-03, 4.99852801234917238e-03, 2.30417297573763929e-05, 2.85885980666130812e-04), # uranus Planet.new( 1.28943695621391310e+01, -1.51111514016986312e+01, -2.23307578892655734e-01, 2.96460137564761618e-03, 2.37847173959480950e-03, -2.96589568540237556e-05, 4.36624404335156298e-05), # neptune Planet.new( 1.53796971148509165e+01, -2.59193146099879641e+01, 1.79258772950371181e-01, 2.68067772490389322e-03, 1.62824170038242295e-03, -9.51592254519715870e-05, 5.15138902046611451e-05) ] init = 200_000 # ARGV[0] n = Integer(init) offset_momentum(BODIES) puts "%.9f" % energy(BODIES) nbodies = BODIES.size dt = 0.01 n.times do i = 0 while i < nbodies b = BODIES[i] b.move_from_i(BODIES, nbodies, dt, i + 1) i += 1 end end puts "%.9f" % energy(BODIES) ruby 1.8.6 (2007-12-03) [x86_64-linux] .28.3777990341187 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .11.6796798706055 ----------------------------------------------------------- so_nested_loop #!/usr/bin/ruby # -*- mode: ruby -*- # $Id: nestedloop-ruby.code,v 1.4 2004/11/13 07:42:22 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ # from Avi Bryant n = 16 # Integer(ARGV.shift || 1) x = 0 n.times do n.times do n.times do n.times do n.times do n.times do x += 1 end end end end end end # puts x ruby 1.8.6 (2007-12-03) [x86_64-linux] .11.4682841300964 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .2.29553294181824 ----------------------------------------------------------- so_nsieve # The Computer Language Shootout # http://shootout.alioth.debian.org/ # # contributed by Glenn Parker, March 2005 # modified by Evan Phoenix, Sept 2006 def sieve(m) flags = Flags.dup[0,m] count = 0 pmax = m - 1 p = 2 while p <= pmax unless flags[p].zero? count += 1 mult = p while mult <= pmax flags[mult] = 0 mult += p end end p += 1 end count end n = 9 # (ARGV[0] || 2).to_i Flags = ("\x1" * ( 2 ** n * 10_000)).unpack("c*") n.downto(n-2) do |exponent| break if exponent < 0 m = (1 << exponent) * 10_000 # m = (2 ** exponent) * 10_000 count = sieve(m) printf "Primes up to %8d %8d\n", m, count end ruby 1.8.6 (2007-12-03) [x86_64-linux] .27.8629460334778 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .6.61286902427673 ----------------------------------------------------------- so_nsieve_bits #!/usr/bin/ruby # # The Great Computer Language Shootout # http://shootout.alioth.debian.org/ # # nsieve-bits in Ruby # Contributed by Glenn Parker, March 2005 CharExponent = 3 BitsPerChar = 1 << CharExponent LowMask = BitsPerChar - 1 def sieve(m) items = "\xFF" * ((m / BitsPerChar) + 1) masks = "" BitsPerChar.times do |b| masks << (1 << b).chr end count = 0 pmax = m - 1 2.step(pmax, 1) do |p| if items[p >> CharExponent][p & LowMask] == 1 count += 1 p.step(pmax, p) do |mult| a = mult >> CharExponent b = mult & LowMask items[a] -= masks[b] if items[a][b] != 0 end end end count end n = 9 # (ARGV[0] || 2).to_i n.step(n - 2, -1) do |exponent| break if exponent < 0 m = 2 ** exponent * 10_000 count = sieve(m) printf "Primes up to %8d %8d\n", m, count end ruby 1.8.6 (2007-12-03) [x86_64-linux] .74.7709109783173 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .8.90028190612793 ----------------------------------------------------------- so_object #!/usr/bin/ruby # -*- mode: ruby -*- # $Id: objinst-ruby.code,v 1.4 2004/11/13 07:42:25 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ # with help from Aristarkh Zagorodnikov class Toggle def initialize(start_state) @bool = start_state end def value @bool end def activate @bool = !@bool self end end class NthToggle < Toggle def initialize(start_state, max_counter) super start_state @count_max = max_counter @counter = 0 end def activate @counter += 1 if @counter >= @count_max @bool = !@bool @counter = 0 end self end end n = 1500000 # (ARGV.shift || 1).to_i toggle = Toggle.new 1 5.times do toggle.activate.value ? 'true' : 'false' end n.times do toggle = Toggle.new 1 end ntoggle = NthToggle.new 1, 3 8.times do ntoggle.activate.value ? 'true' : 'false' end n.times do ntoggle = NthToggle.new 1, 3 end ruby 1.8.6 (2007-12-03) [x86_64-linux] .8.86674499511719 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.98283505439758 ----------------------------------------------------------- so_partial_sums n = 2_500_000 # (ARGV.shift || 1).to_i alt = 1.0 ; s0 = s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = 0.0 1.upto(n) do |d| d = d.to_f ; d2 = d * d ; d3 = d2 * d ; ds = Math.sin(d) ; dc = Math.cos(d) s0 += (2.0 / 3.0) ** (d - 1.0) s1 += 1.0 / Math.sqrt(d) s2 += 1.0 / (d * (d + 1.0)) s3 += 1.0 / (d3 * ds * ds) s4 += 1.0 / (d3 * dc * dc) s5 += 1.0 / d s6 += 1.0 / d2 s7 += alt / d s8 += alt / (2.0 * d - 1.0) alt = -alt end if false printf("%.9f\t(2/3)^k\n", s0) printf("%.9f\tk^-0.5\n", s1) printf("%.9f\t1/k(k+1)\n", s2) printf("%.9f\tFlint Hills\n", s3) printf("%.9f\tCookson Hills\n", s4) printf("%.9f\tHarmonic\n", s5) printf("%.9f\tRiemann Zeta\n", s6) printf("%.9f\tAlternating Harmonic\n", s7) printf("%.9f\tGregory\n", s8) end ruby 1.8.6 (2007-12-03) [x86_64-linux] .32.7498679161072 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .12.1965389251709 ----------------------------------------------------------- so_pidigits # 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 ruby 1.8.6 (2007-12-03) [x86_64-linux] .2.41420793533325 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .2.80991005897522 ----------------------------------------------------------- so_random # from http://www.bagley.org/~doug/shootout/bench/random/random.ruby IM = 139968.0 IA = 3877.0 IC = 29573.0 $last = 42.0 def gen_random(max) (max * ($last = ($last * IA + IC) % IM)) / IM end N = 1000000 i=0 while i/ if seq.length != 0 revcomp(seq.join) seq=Array.new end puts $_ else $_.sub(/\n/,'') seq.push $_ end end revcomp(seq.join) ruby 1.8.6 (2007-12-03) [x86_64-linux] .4.14339995384216 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .4.04299592971802 ----------------------------------------------------------- so_sieve # from http://www.bagley.org/~doug/shootout/bench/sieve/sieve.ruby num = 40 count = i = j = 0 flags0 = Array.new(8192,1) k = 0 while k < num k+=1 count = 0 flags = flags0.dup i = 2 while i<8192 i+=1 if flags[i] # remove all multiples of prime: i j = i*i while j < 8192 j += i flags[j] = nil end count += 1 end end end count ruby 1.8.6 (2007-12-03) [x86_64-linux] .0.849525928497314 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.187962055206299 ----------------------------------------------------------- so_spectralnorm # The Computer Language Shootout # http://shootout.alioth.debian.org/ # Contributed by Sokolov Yura def eval_A(i,j) return 1.0/((i+j)*(i+j+1)/2+i+1) end def eval_A_times_u(u) v, i = nil, nil (0..u.length-1).collect { |i| v = 0 for j in 0..u.length-1 v += eval_A(i,j)*u[j] end v } end def eval_At_times_u(u) v, i = nil, nil (0..u.length-1).collect{|i| v = 0 for j in 0..u.length-1 v += eval_A(j,i)*u[j] end v } end def eval_AtA_times_u(u) return eval_At_times_u(eval_A_times_u(u)) end n = 500 # ARGV[0].to_i u=[1]*n for i in 1..10 v=eval_AtA_times_u(u) u=eval_AtA_times_u(v) end vBv=0 vv=0 for i in 0..n-1 vBv += u[i]*v[i] vv += v[i]*v[i] end str = "%0.9f" % (Math.sqrt(vBv/vv)), "\n" # print str ruby 1.8.6 (2007-12-03) [x86_64-linux] .41.4432969093323 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .12.4843308925629 ----------------------------------------------------------- vm1_block def m yield end i=0 while i<30000000 # while loop 1 i+=1 m{ } end ruby 1.8.6 (2007-12-03) [x86_64-linux] .47.5090911388397 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .5.34108591079712 ----------------------------------------------------------- vm1_const Const = 1 i = 0 while i<30000000 # while loop 1 i+= 1 j = Const k = Const end ruby 1.8.6 (2007-12-03) [x86_64-linux] .23.1181719303131 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .2.43142795562744 ----------------------------------------------------------- vm1_ensure i=0 while i<30000000 # benchmark loop 1 i+=1 begin begin ensure end ensure end end ruby 1.8.6 (2007-12-03) [x86_64-linux] .37.892012834549 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.93873500823975 ----------------------------------------------------------- vm1_ivar @a = 1 i = 0 while i<30000000 # while loop 1 i+= 1 j = @a k = @a end ruby 1.8.6 (2007-12-03) [x86_64-linux] .21.4678978919983 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .3.85475015640259 ----------------------------------------------------------- vm1_ivar_set i = 0 while i<30_000_000 # while loop 1 i+= 1 @a = 1 @b = 2 end ruby 1.8.6 (2007-12-03) [x86_64-linux] .21.2300369739532 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .4.83743500709534 ----------------------------------------------------------- vm1_length a = 'abc' b = [1, 2, 3] i=0 while i<30000000 # while loop 1 i+=1 a.length b.length end ruby 1.8.6 (2007-12-03) [x86_64-linux] .24.722156047821 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .3.72566795349121 ----------------------------------------------------------- vm1_neq i = 0 obj1 = Object.new obj2 = Object.new while i<30000000 # while loop 1 i+= 1 obj1 != obj2 end ruby 1.8.6 (2007-12-03) [x86_64-linux] .20.6118760108948 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .3.06124901771545 ----------------------------------------------------------- vm1_not i = 0 obj = Object.new while i<30000000 # while loop 1 i+= 1 !obj end ruby 1.8.6 (2007-12-03) [x86_64-linux] .16.1265139579773 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .2.3499960899353 ----------------------------------------------------------- vm1_rescue i=0 while i<30000000 # while loop 1 i+=1 begin rescue end end ruby 1.8.6 (2007-12-03) [x86_64-linux] .24.3832228183746 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.55430102348328 ----------------------------------------------------------- vm1_simplereturn def m return 1 end i=0 while i<30000000 # while loop 1 i+=1 m end ruby 1.8.6 (2007-12-03) [x86_64-linux] .39.7903399467468 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .3.70241904258728 ----------------------------------------------------------- vm1_swap a = 1 b = 2 i=0 while i<30000000 # while loop 1 i+=1 a, b = b, a end ruby 1.8.6 (2007-12-03) [x86_64-linux] .25.7141978740692 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .2.88358116149902 ----------------------------------------------------------- vm2_array i=0 while i<6000000 # benchmark loop 2 i+=1 a = [1,2,3,4,5,6,7,8,9,10] end ruby 1.8.6 (2007-12-03) [x86_64-linux] .7.03480696678162 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .2.76925206184387 ----------------------------------------------------------- vm2_case i=0 while i<6000000 # while loop 2 case :foo when :bar raise when :baz raise when :boo raise when :foo i+=1 end end ruby 1.8.6 (2007-12-03) [x86_64-linux] .5.43204402923584 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.715604066848755 ----------------------------------------------------------- vm2_eval i=0 while i<6000000 # benchmark loop 2 i+=1 eval("1") end ruby 1.8.6 (2007-12-03) [x86_64-linux] .17.8432769775391 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .46.1212179660797 ----------------------------------------------------------- vm2_method def m nil end i=0 while i<6000000 # benchmark loop 2 i+=1 m; m; m; m; m; m; m; m; end ruby 1.8.6 (2007-12-03) [x86_64-linux] .28.2497239112854 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .4.29976391792297 ----------------------------------------------------------- vm2_mutex require 'thread' m = Mutex.new i=0 while i<6000000 # benchmark loop 2 i+=1 m.synchronize{} end ruby 1.8.6 (2007-12-03) [x86_64-linux] .10.6425650119781 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .2.34252882003784 ----------------------------------------------------------- vm2_poly_method class C1 def m 1 end end class C2 def m 2 end end o1 = C1.new o2 = C2.new i=0 while i<6000000 # benchmark loop 2 o = (i % 2 == 0) ? o1 : o2 o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m i+=1 end ruby 1.8.6 (2007-12-03) [x86_64-linux] .33.5412700176239 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .4.6308810710907 ----------------------------------------------------------- vm2_poly_method_ov class C1 def m 1 end end class C2 def m 2 end end o1 = C1.new o2 = C2.new i=0 while i<6000000 # benchmark loop 2 o = (i % 2 == 0) ? o1 : o2 # o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m i+=1 end ruby 1.8.6 (2007-12-03) [x86_64-linux] .5.7778160572052 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.930914878845215 ----------------------------------------------------------- vm2_proc def m &b b end pr = m{ a = 1 } i=0 while i<6000000 # benchmark loop 2 i+=1 pr.call end ruby 1.8.6 (2007-12-03) [x86_64-linux] .10.2587428092957 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.44363212585449 ----------------------------------------------------------- vm2_regexp i=0 str = 'xxxhogexxx' while i<6000000 # benchmark loop 2 /hoge/ =~ str i+=1 end ruby 1.8.6 (2007-12-03) [x86_64-linux] .5.10241913795471 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .2.87602686882019 ----------------------------------------------------------- vm2_send class C def m end end o = C.new i=0 while i<6000000 # benchmark loop 2 i+=1 o.__send__ :m end ruby 1.8.6 (2007-12-03) [x86_64-linux] .7.12156820297241 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.859764099121094 ----------------------------------------------------------- vm2_super class C def m 1 end end class CC < C def m super() end end obj = CC.new i = 0 while i<6000000 # benchmark loop 2 obj.m i+=1 end ruby 1.8.6 (2007-12-03) [x86_64-linux] .9.18226003646851 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.45039200782776 ----------------------------------------------------------- vm2_unif1 i = 0 def m a, b end while i<6000000 # benchmark loop 2 i+=1 m 100, 200 end ruby 1.8.6 (2007-12-03) [x86_64-linux] .6.42444896697998 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .0.910121917724609 ----------------------------------------------------------- vm2_zsuper i = 0 class C def m a 1 end end class CC < C def m a super end end obj = CC.new while i<6000000 # benchmark loop 2 obj.m 10 i+=1 end ruby 1.8.6 (2007-12-03) [x86_64-linux] .9.9683849811554 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .1.4930579662323 ----------------------------------------------------------- vm3_thread_create_join i=0 while i<100_000 # benchmark loop 3 i+=1 Thread.new{ }.join end ruby 1.8.6 (2007-12-03) [x86_64-linux] .1.16788816452026 ruby 1.9.0 (2007-12-25 revision 14709) [x86_64-linux] .3.24958300590515 ----------------------------------------------------------- vm3_thread_mutex require 'thread' m = Mutex.new r = 0 max = 1000 (1..max).map{ Thread.new{ i=0 while i