Я новичок в Haskell и писал код для решения проблемы решета Эратосфена с использованием списков. Вот код
primes m = 2 : primes' m [3,5 ..m] [] where
primes' m integers@(p : xs) acc | p*p>m = reverse acc ++ integers
| True = primes' m (xs `remove` [p*p, p*p+2*p..m]) (p:acc)
remove integers@(x:xs) multiples@(y:ys) | x < y = x : remove xs multiples
| x == y = remove xs ys
| x > y = remove integers ys
remove integers multiples = integers
Если я ввожу m = 2000000, коду требуется около 14 секунд, чтобы распечатать все результаты. Я думаю, что 90 процентов времени уходит на печать, а не на выполнение кода. Есть ли способ найти правильное время выполнения для этой конкретной программы?
remove
выглядит так, будто ему нужно пройти через все неудаленные числа. Настоящее сито Эратосфена может прыгать прямо к флагам для чисел, которые оно помечает составными, что намного быстрее. Эмпирическое правило: если нет массива логических флагов, это, вероятно, не решето Эратосфена. - person user2357112 supports Monica   schedule 20.06.2018remove
ОП - этоData.List.Ordered.minus
. конечно, у массивов есть преимущество произвольного доступа, но реализация с упорядоченными списками может иметь только дополнительный логарифмический фактор в сложности. подробнее здесь. - person Will Ness   schedule 21.06.2018remove
действительно проходит все числа, но итерация останавливается раньше, на кв. м. верхнего предела. так что в целом это примерноprimesTo m = foldl minus [3,5..] [[p*p, p*p+2*p..m] | p <- takeWhile ((<= m) . (^2)) primes]
. Который, как показывает Мелисса О'Нил в своей статье JFP, имеет сложность чуть выше n ^ 1,5. - person Will Ness   schedule 21.06.2018(...(((xs -a)-b)-c)-...)
превратить в foldr-based(xs -(a+(b+(c+...))))
, и если, далее, сумма будет найдена в виде дерева, а не списка, то сложность будет всего вlog N
раз хуже, чем решето случайного доступа (то же самое как на основе PQ в статье, кстати). Насколько нам известно, сам Эратосфен считал единицами. :) здесь по крайней мере каждое перечисление напрямую находит каждое следующее кратное, добавляя2*p
, а не добавляя1
2p раз. Так что я считаю это настоящим решетом. - person Will Ness   schedule 21.06.2018