👻 Check our latest review to choose the best laptop for Machine Learning engineers and Deep learning tasks!
I have taken Problem #12 from Project Euler as a programming exercise and to compare my (surely not optimal) implementations in C, Python, Erlang and Haskell. In order to get some higher execution times, I search for the first triangle number with more than 1000 divisors instead of 500 as stated in the original problem.
The result is the following:
C:
[email protected]:~/erlang$ gcc -lm -o euler12.bin euler12.c
[email protected]:~/erlang$ time ./euler12.bin
842161320
real 0m11.074s
user 0m11.070s
sys 0m0.000s
Python:
[email protected]:~/erlang$ time ./euler12.py
842161320
real 1m16.632s
user 1m16.370s
sys 0m0.250s
Python with PyPy:
[email protected]:~/Downloads/pypy-c-jit-43780-b590cf6de419-linux64/bin$ time ./pypy /home/lorenzo/erlang/euler12.py
842161320
real 0m13.082s
user 0m13.050s
sys 0m0.020s
Erlang:
[email protected]:~/erlang$ erlc euler12.erl
[email protected]:~/erlang$ time erl -s euler12 solve
Erlang R13B03 (erts-5.7.4) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.7.4 (abort with ^G)
1> 842161320
real 0m48.259s
user 0m48.070s
sys 0m0.020s
Haskell:
[email protected]:~/erlang$ ghc euler12.hs -o euler12.hsx
[1 of 1] Compiling Main ( euler12.hs, euler12.o )
Linking euler12.hsx ...
[email protected]:~/erlang$ time ./euler12.hsx
842161320
real 2m37.326s
user 2m37.240s
sys 0m0.080s
Summary:
- C: 100%
- Python: 692% (118% with PyPy)
- Erlang: 436% (135% thanks to RichardC)
- Haskell: 1421%
I suppose that C has a big advantage as it uses long for the calculations and not arbitrary length integers as the other three. Also it doesn"t need to load a runtime first (Do the others?).
Question 1:
Do Erlang, Python and Haskell lose speed due to using arbitrary length integers or don"t they as long as the values are less than MAXINT
?
Question 2: Why is Haskell so slow? Is there a compiler flag that turns off the brakes or is it my implementation? (The latter is quite probable as Haskell is a book with seven seals to me.)
Question 3: Can you offer me some hints how to optimize these implementations without changing the way I determine the factors? Optimization in any way: nicer, faster, more "native" to the language.
EDIT:
Question 4: Do my functional implementations permit LCO (last call optimization, a.k.a tail recursion elimination) and hence avoid adding unnecessary frames onto the call stack?
I really tried to implement the same algorithm as similar as possible in the four languages, although I have to admit that my Haskell and Erlang knowledge is very limited.
Source codes used:
#include <stdio.h>
#include <math.h>
int factorCount (long n)
{
double square = sqrt (n);
int isquare = (int) square;
int count = isquare == square ? -1 : 0;
long candidate;
for (candidate = 1; candidate <= isquare; candidate ++)
if (0 == n % candidate) count += 2;
return count;
}
int main ()
{
long triangle = 1;
int index = 1;
while (factorCount (triangle) < 1001)
{
index ++;
triangle += index;
}
printf ("%ld
", triangle);
}
#! /usr/bin/env python3.2
import math
def factorCount (n):
square = math.sqrt (n)
isquare = int (square)
count = -1 if isquare == square else 0
for candidate in range (1, isquare + 1):
if not n % candidate: count += 2
return count
triangle = 1
index = 1
while factorCount (triangle) < 1001:
index += 1
triangle += index
print (triangle)
-module (euler12).
-compile (export_all).
factorCount (Number) -> factorCount (Number, math:sqrt (Number), 1, 0).
factorCount (_, Sqrt, Candidate, Count) when Candidate > Sqrt -> Count;
factorCount (_, Sqrt, Candidate, Count) when Candidate == Sqrt -> Count + 1;
factorCount (Number, Sqrt, Candidate, Count) ->
case Number rem Candidate of
0 -> factorCount (Number, Sqrt, Candidate + 1, Count + 2);
_ -> factorCount (Number, Sqrt, Candidate + 1, Count)
end.
nextTriangle (Index, Triangle) ->
Count = factorCount (Triangle),
if
Count > 1000 -> Triangle;
true -> nextTriangle (Index + 1, Triangle + Index + 1)
end.
solve () ->
io:format ("~p~n", [nextTriangle (1, 1) ] ),
halt (0).
factorCount number = factorCount" number isquare 1 0 - (fromEnum $ square == fromIntegral isquare)
where square = sqrt $ fromIntegral number
isquare = floor square
factorCount" number sqrt candidate count
| fromIntegral candidate > sqrt = count
| number ’mod’ candidate == 0 = factorCount" number sqrt (candidate + 1) (count + 2)
| otherwise = factorCount" number sqrt (candidate + 1) count
nextTriangle index triangle
| factorCount triangle > 1000 = triangle
| otherwise = nextTriangle (index + 1) (triangle + index + 1)
main = print $ nextTriangle 1 1
👻 Read also: what is the best laptop for engineering students?
We hope this article has helped you to resolve the problem. Apart from Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell, check other __main__ Python module-related topics.
Want to excel in Python? See our review of the best Python online courses 2023. If you are interested in Data Science, check also how to learn programming in R.
By the way, this material is also available in other languages:
- Italiano Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
- Deutsch Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
- Français Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
- Español Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
- Türk Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
- Русский Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
- Português Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
- Polski Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
- Nederlandse Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
- 中文 Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
- 한국어 Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
- 日本語 Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
- हिन्दी Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
Boston | 2023-02-01
Ev PHP module is always a bit confusing 😭 Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell is not the only problem I encountered. I just hope that will not emerge anymore
Massachussetts | 2023-02-01
os Python module is always a bit confusing 😭 Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell is not the only problem I encountered. I am just not quite sure it is the best method
London | 2023-02-01
Thanks for explaining! I was stuck with Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell for some hours, finally got it done 🤗. Will use it in my bachelor thesis