Обновление: Эликсир не медленный, мой алгоритм был. Мои алгоритмы не были даже яблоками для сравнения яблок. См. Ответы на римские ответы ниже для эквивалентных алгоритмов Ruby и Go. Также благодаря José мой медленный алгоритм может быть значительно ускорен, просто префикс MIX_ENV = prod. Я обновил статистику в вопросе.
Оригинальный вопрос: Я работаю над проблемами Project Euler на нескольких языках, чтобы увидеть, насколько продуктивны и насколько быстрыми являются языки. В проблема № 5 нам предлагается найти наименьшее положительное число, которое равномерно делится на все числа от 1 до 20.
Я реализовал решение на нескольких языках. Вот статистика:
- Go 1.4.2: 0.58s
- Ruby 2.2 MRI: 6.7s
- Elixir 1.0.5 (мой первый алгоритм): 57s
- Elixir 1.0.5 (мой первый алгоритм с префиксом MIX_ENV = prod): 7.4s
- Elixir 1.0.5 (эквивалентный алгоритм Roman Go): 0.7s
- Elixir 1.0.5 (римский эквивалентный алгоритм Ruby): 1.8s
Почему производительность Elixir настолько медленная? Я попытался использовать ту же оптимизацию на всех языках. Предостережение: я новичок FP и Elixir.
Есть ли что-нибудь, что я могу сделать, чтобы улучшить производительность в Elixir? Если вы использовали какие-либо инструменты для профилирования при разработке лучшего решения, не могли бы вы включить их в ответ?
В 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")
}
В 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
В Эликсире:
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