Update: Elixir isn't slow, my algorithm was. My algorithms weren't even apples to apples comparison. See Roman's answers below for Ruby and Go equivalent algorithms. Also thanks to José, my slow algorithm can be significantly sped up by just prefixing MIX_ENV=prod. I've updated the stats in the question.
Original question: I'm working on Project Euler problems in multiple languages just to see how productive and how fast languages are. In problem #5, we are asked to find the smallest positive number that is evenly divisible by all of the numbers from 1 to 20.
I implemented the solution in multiple languages. Here are the stats:
- Go 1.4.2 : 0.58s
- Ruby 2.2 MRI : 6.7s
- Elixir 1.0.5 (my first algorithm) : 57s
- Elixir 1.0.5 (my first algorithm with MIX_ENV=prod prefix): 7.4s
- Elixir 1.0.5 (Roman's Go equivalent algorithm) : 0.7s
- Elixir 1.0.5 (Roman's Ruby equivalent algorithm) : 1.8s
Why is Elixir's performance so slow? I tried using the same optimizations in all languages. Caveat: I'm a FP and Elixir newbie.
Is there anything I can do to improve the performance in Elixir? If you used any profiling tools in figuring out a better solution, could you please include them in the response?
In Go:
func problem005() int {
i := 20
outer:
for {
for j := 20; j > 0; j-- {
if i%j != 0 {
i = i + 20
continue outer
}
}
return i
}
panic("Should have found a solution by now")
}
In Ruby:
def self.problem005
divisors = (1..20).to_a.reverse
number = 20 # we iterate over multiples of 20
until divisors.all? { |divisor| number % divisor == 0 } do
number += 20
end
return number
end
In Elixir:
def problem005 do
divisible_all? = fn num ->
Enum.all?((20..2), &(rem(num, &1) == 0))
end
Stream.iterate(20, &(&1 + 20))
|> Stream.filter(divisible_all?)
|> Enum.fetch! 0
end