Reputation: 171
I was working on the Project Euler problems, when I stumbled on this problem. I wrote a program that solves it correctly in Ruby on Rails (new to the language):
class Collatz
def search
counter = 0
storage = 0
amount = 0
(1..1000000).each do |i| i += 1
temp = i
while temp != 1
temp = temp & 1 == 1 ? 3 * temp + 1 : temp >> 1
counter += 1
end
if counter > amount
amount = counter
storage = i
end
counter = 0
end
puts storage
end
end
start = Time.now
collatz = Collatz.new
collatz.search
ending = Time.now
puts "Time: #{ending - start}"
I realized that it took a very long time, 15.185317 seconds to be exact. When I try Java, however, the time is much shorter:
public class Euler{
private static void problem() {
long a;
int j;
int max = 0;
int maxnr = 0;
for(int i = 1; i < 1000000; i++) {
a = i;
j = 1;
while( a != 1 ) {
a = ((a & 1) == 1) ? (3 * a + 1) : (a >> 1);
j++;
}
if(j > max) {
max = j;
maxnr = i;
}
}
System.out.println(maxnr);
}
public static void main(String[] args) {
long ct = System.currentTimeMillis();
problem();
long nt = System.currentTimeMillis() - ct;
System.out.println(nt);
}
In the end this program took 769 milliseconds. I am using RubyMine for Ruby and Intellij IDEA for Java. I can't seem to figure out why it takes so long, and I'm not sure if it is normal or not. The task doesn't seem too difficult, since I'm just looping.
Upvotes: 1
Views: 287
Reputation: 16651
Your solution to this problem is quite poor. It involves doing an enormous amount of duplicate work. Apparantly, the JVM is a lot better at optimizing this redundant work than Ruby.
However, if you would write a proper solution, which explicitly uses previous work you will find that it won't matter if you run it on Ruby or Java. You can do this by using an array or a map to store previous results. This technique is also known as dynamic programming.
Upvotes: 3