In order to solve the Euler Project problem n°5, I wrote the following program:
class p5
{
const int maxNumber = 20;
static void Main(string[] args)
Well, one thing is that you only have to test even numbers, so start at 0, and increase by 2. this is due to the fact that an even number will never evenly divide into an odd number. you could also start the search at a factorial of 10, so 10*9*8*7..and so on so other words start at 10! which is 3 628 800. that may help run it faster. also on average my speed in C was 10 seconds, so you're code is actually fine.
A good optimization would be using a better algorithm.
This is asking for the least common multiple of the numbers 1..20, which can be calculated successive by finding lcm(1,2), then lcm(lcm(1,2),3) etc until 20.
A simple algorithm for finding the lcm is dividing the product of the two numbers by the greatest common divisor. The gcd can be found by the well known euklidian algorithm in a very short time.
#include <iostream>
long gcd(long a, long b) {
if (!b) return a;
return gcd(b, a-b*(a/b));
}
long lcm(long a, long b) {
return (a*b)/gcd(a, b);
}
int main(int argc, char** argv) {
long x = 1;
for (long i=2; i<20; ++i)
x = lcm(x, i);
std::cout << x << std::endl;
}
This spits out the solution instantly.
Using Enumerable is slow (see this for comparison of Enumerable.Repeat and for loop for initialization of an array). Try plain while/for loop like this:
int maxNumber = 21;
int n = 1;
bool found = false;
while(!found)
{
found = true;
for(int i = 1; i < maxNumber; i++)
{
if(n % i != 0)
{
found = false;
break;
}
}
n++;
}
return n-1;
This runs for about 4 seconds on my computer in debug.
EDIT
When considering further optimizations, it is better to start testing modulo of larger numbers, so when I changed the for loop to:
for (int i = maxNumber; i > 1; i--)
the time dropped to under 2 seconds.
A mathematical insight would be that we only have to test divisibility by numbers that are not multiples of the numbers we already tested. In our case we can write:
private int[] p = { 19, 17, 16, 13, 11, 9, 7, 5, 4, 3, 2 };
int Job()
{
int n = 1;
bool found = false;
while (!found)
{
found = true;
foreach (int i in p)
{
if (n % i != 0)
{
found = false;
break;
}
}
n++;
}
return n - 1;
}
However, this is actually slower, about 2.5 seconds.