TL;DR: Long-winded post that is me trying to defend Python (my language of choice) against C#. In this example, C# performs better, but still takes more lines of code to do the same amount of work, but the final performance benefit is that C# is ~5x faster than a similar approach in Python when coded correctly. The end result is that you should use the language that suits you.
When I run the C# example, it took about 3 seconds to complete on my machine, and gave me a result of 232,792,560. It could be optimized using the known fact that you can only have a number divisible by numbers from 1 to 20 if the number is a multiple of 20, and therefore you don't need to increment by 1, but instead 20. That single optimization made the code execute ~10x faster in a mere 353 milliseconds.
When I run the Python example, I gave up on waiting and tried to write my own version using itertools, which didn't have much better success, and was taking about as long as your example. Then I hit upon an acceptable version of itertools, if I take into account that only multiples of my largest number could be divisible by all numbers from smallest to largest. As such, the refined Python(3.6) code is here with a decorator timing function that prints the number of seconds it took to execute:
import time
from itertools import count, filterfalse
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
print(time.time() - start)
return res
return wrapper
@timer
def test(stop):
return next(filterfalse(lambda x: any(x%i for i in range(2, stop)), count(stop, stop)))
print("Test Function")
print(test(20))
# 11.526668787002563
# 232792560
This also reminded me of a question I recently had to answer on CodeFights for Least Common Multiple using the Greatest Common Denominator function in Python. That code is as follows:
import time
from fractions import gcd
from functools import reduce
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
print(time.time() - start)
return res
return wrapper
@timer
def leastCommonDenominator(denominators):
return reduce(lambda a, b: a * b // gcd(a, b), denominators)
print("LCM Function")
print(leastCommonDenominator(range(1, 21)))
# 0.001001596450805664
# 232792560
As in most programming tasks, sometimes the simplest approach isn't always the fastest. Unfortunately, it really stuck out when attempted in Python this time. That said, the beauty in Python is the simplicity of getting a performant execution, where it took 10 lines of C#, I was able to return the correct answer in (potentially) a one-line lambda expression, and 300-times faster than my simple optimization on C#. I'm no specialist in C#, but implementing the same approach here is the code I used and its result (about 5x faster than Python):
using System;
using System.Diagnostics;
namespace ConsoleApp1
{
class Program
{
public static void Main(string[] args)
{
Stopwatch t0 = new Stopwatch();
int maxNumber = 20;
long start;
t0.Start();
start = Orig(maxNumber);
t0.Stop();
Console.WriteLine("Original | {0:d}, {1:d}", maxNumber, start);
// Original | 20, 232792560
Console.WriteLine("Original | time elapsed = {0}.", t0.Elapsed);
// Original | time elapsed = 00:00:02.0585575
t0.Restart();
start = Test(maxNumber);
t0.Stop();
Console.WriteLine("Test | {0:d}, {1:d}", maxNumber, start);
// Test | 20, 232792560
Console.WriteLine("Test | time elapsed = {0}.", t0.Elapsed);
// Test | time elapsed = 00:00:00.0002763
Console.ReadLine();
}
public static long Orig(int maxNumber)
{
bool found = false;
long start = 0;
while (!found)
{
start += maxNumber;
found = true;
for (int i=2; i < 21; i++)
{
if (start % i != 0)
found = false;
}
}
return start;
}
public static long Test(int maxNumber)
{
long result = 1;
for (long i = 2; i <= maxNumber; i++)
{
result = (result * i) / GCD(result, i);
}
return result;
}
public static long GCD(long a, long b)
{
while (b != 0)
{
long c = b;
b = a % b;
a = c;
}
return a;
}
}
}
For most higher-level tasks, however, I usually see Python doing exceptionally well in comparison to a .NET implementation, though I cannot substantiate the claims at this time, aside from saying the Python Requests library has given me as much as a double to triple return in performance compared to a C# WebRequest written the same way. This was also true when writing Selenium processes, as I could read text elements in Python in 100 milliseconds or less, but each element retrieval took C# >1 second to return. That said, I actually prefer the C# implementation because of its object-oriented approach, where Python's Selenium implementation goes functional which gets very hard to read at times.