GolfScript, 22/20 (20/19) байтов
n(6?,:|2>{(.p|%-.}do:n
За счет скорости код можно сделать на два байта короче:
n(6?,:|2>.{|%2>-}/n*
Если выходной формат, указанный в отредактированном вопросе, игнорируется (что и делают многие из существующих ответов), в быстрой версии можно сохранить два байта, а в медленной - один.
n(6?,:|2>{(.p|%-.}do
n(6?,:|2>.{|%2>-}/`
Это напечатает дополнительный LF после простых чисел для быстрой версии, и это напечатает простые числа как массив для медленной.
Как это устроено
Обе версии являются реализациями сита Эратосфена .
Быстрая версия делает следующее:
Установите A = [ 2 3 4 … 999,999 ]
и | = [ 0 1 2 … 999,999 ]
.
Установите N = A[0]
и распечатайте N
.
Соберите каждый N-й элемент из |
in C
. Это кратные N
.
Set A = A - C
.
Если A
не пусто, вернитесь к 2.
n(6? # Push "\n".pop() ** 6 = 1,000,000.
,:| # Push | = [ 0 1 2 … 999,999 ].
,2> # Push A = [ 2 3 4 … 999,999 ].
{ #
( # Unshift the first element (“N”) of “A”.
.p # Print “N”.
|% # Collect every N-th element from “A” into a new array, starting with the first.
- # Take the set difference of “A” and the array from above.
. # Duplicate the set difference.
}do # If the set difference is non-empty, repeat.
:n # Store the empty string in “n”, so no final LF will get printed.
Медленная версия работает аналогичным образом, но вместо последовательного удаления кратных минимума «А» (который всегда является простым), она удаляет кратные всех положительных целых чисел ниже 1 000 000.
конкурентоспособность
В отсутствие каких-либо встроенных математических функций для разложения на множители или проверки на первичность все решения GolfScript будут либо очень большими, либо очень неэффективными.
Хотя это еще далеко от эффективности, я думаю, что достиг приличного соотношения скорости и размера. На момент представления этот подход, по-видимому, является самым коротким из тех, которые не используют ни одну из вышеупомянутых встроенных программ. Я говорю кажется потому что я понятия не имею, как работают некоторые ответы ...
Я протестировал все четыре представленных решения GolfScript: w0lf (пробное деление), другой мой ответ (теорема Уилсона) и два из этого ответа. Это были результаты:
Bound | Trial division | Sieve (slow) | Wilson's theorem | Sieve (fast)
----------+--------------------+--------------------+------------------+----------------
1,000 | 2.47 s | 0.06 s | 0.03 s | 0.03 s
10,000 | 246.06 s (4.1 m) | 1.49 s | 0.38 s | 0.14 s
20,000 | 1006.83 s (16.8 m) | 5.22 s | 1.41 s | 0.38 s
100,000 | ~ 7 h (estimated) | 104.65 (1.7 m) | 35.20 s | 5.82 s
1,000,000 | ~ 29 d (estimated) | 111136.97s (3.1 h) | 3695.92 s (1 h) | 418.24 s (7 m)