Created
March 12, 2012 05:53
-
-
Save funny-falcon/2020108 to your computer and use it in GitHub Desktop.
uglier is sometimes faster
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
#!/usr/bin/env ruby | |
require 'yaml' | |
y=[] | |
(1..10000).each{|x| | |
#next unless x/2==(1.0*x)/2 | |
z=x | |
divisors=[1] | |
_continue=true | |
while _continue | |
_continue=false | |
((divisors.last+1)..z).each{|w| | |
r=z/w | |
if (1.0*z)/w==r && w<x | |
divisors<<w | |
_continue=true | |
break | |
end | |
} | |
end | |
if divisors.inject(&:+)>x and (3..(divisors.count)).find{|w| divisors.combination(w).find{|w2| w2.inject(&:+)==x } } | |
y<<x | |
end | |
} | |
puts "amount: #{y.count}" |
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
#!/usr/bin/env ruby | |
require 'yaml' | |
class Test | |
attr_reader :y | |
def initialize(up) | |
@up = up | |
@y = [] | |
end | |
def perform | |
for x in 1..@up | |
divisors, w = [1], 1 | |
while (w = get_next(w+1, x)) | |
divisors << w | |
end | |
y << x if sum(divisors) > x && check(divisors, x) | |
end | |
self | |
end | |
def get_next(from, z) | |
w = from | |
while w < z | |
return w if z/w == (1.0*z)/w | |
w += 1 | |
end | |
nil | |
end | |
def sum(ar) | |
s = ar[0] | |
i, up = 1, ar.size | |
while i < up | |
s += ar[i] | |
i += 1 | |
end | |
s | |
end | |
def check(divisors, x) | |
(3..(divisors.count)).find{|w| | |
divisors.combination(w).find{|w2| | |
sum(w2) == x | |
} | |
} | |
end | |
end | |
puts "amount: #{Test.new(10000).perform.y.count}" |
A small change improves JRuby further... replace the #[] calls in sum with #at calls:
real 0m33.895s
user 0m37.502s
sys 0m0.421s
In JRuby, #[] is flagged as a method that requires a heap-based scope because some versions of it set $~ (backref). Using .at avoids that.
We plan to fix that deoptimization, but it does make a difference right now.
that could be also java version (mine is a bit older):
$ java -version
java version "1.7.0_03"
Java(TM) SE Runtime Environment (build 1.7.0_03-b04)
Java HotSpot(TM) 64-Bit Server VM (build 22.1-b02, mixed mode)
In JRuby, #[] is flagged as a method that requires a heap-based scope because some versions of it set $~ (backref). Using .at avoids that.
Wow :)
@mpapis that certainly could be true. There's also been some optimization work on JRuby master that may not be in your copy.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
My numbers seem to put JRuby farther ahead of Ruby 1.9.3 than your numbers:
Ruby 1.9.3:
111.640000 0.080000 111.720000 (111.722357)
JRuby master on Java 7u4:
41.103000 0.000000 41.103000 ( 41.104000)
JRuby's run time is 36% of Ruby 1.9.3's, compared to around 58% in your case. Nearly 3x faster rather than less than 2x. Perhaps JRuby has improved since this run? Perhaps my dual cores are helping (the JVM does use multiple cores for GC)?