가장 효율적이고 짧은 코드로 된 첫 번째 n 소수 목록 [닫기]


27

규칙은 간단합니다.

  • 우선 N 소수 (이하되지 소수가 없음 ), 표준 출력에 인쇄되어야한다 (소수 코드 내에서 발생해야한다)로 구분 바꿈
  • 내장 함수 또는 라이브러리를 통해 소수 를 생성 할 수 없습니다 . 즉 소수 = get_nth_prime (n), is_a_prime (number) 또는 factorlist = list_all_factors (number)와 같은 내장 함수 또는 라이브러리 함수를 사용하는 것은 그리 독창적이지 않습니다.
  • 채점- 점수 = f ([코드의 문자 수]), O ( f (n))는 알고리즘의 복잡성으로 정의합니다. 여기서 n은 찾은 소수입니다. 예를 들어, 복잡도 가 O (n ^ 2) 인 300 자 코드 인 경우 점수는 300 ^ 2 = 90000 이고 O (n * ln (n)) 인 300 자인 경우 점수는 300 * 5.7 = 1711.13 ( 단순성을 위해 모든 로그를 자연 로그라고 가정합니다.)

  • 기존 프로그래밍 언어를 사용하여 가장 낮은 점수를 획득하십시오

편집 : O (f (n))의 'n'이 무엇인지에 대한 혼란으로 인해 '첫 번째 1000000 소수'에서 '첫 번째 n 소수'로 문제가 변경되었습니다 .n 은 찾은 소수의 수입니다. 여기에있는 문제와 문제의 복잡성은 발견 된 소수에 달려 있습니다)

참고 : 복잡성에 대한 혼란을 명확히하기 위해 'n'이 찾은 소수의 수이고 'N'이 찾은 n 번째 소수이면 n은 n의 측면에서 복잡성은 동일하지 않습니다. 즉 O (f (n))! = O (f (N)) as, f (N)! = constant * f (n) 및 N! = constant * n, n 번째 소수 함수가 선형이 아님을 알기 때문에 'n'을 찾은 이후 소수는 'n'으로 쉽게 표현할 수 있어야합니다.

Kibbee가 지적 했듯이이 사이트 를 방문 하여 솔루션을 확인할 수 있습니다 ( 여기 , 오래된 Google 문서 목록입니다)

이것을 솔루션에 포함하십시오-

  • 프로그램의 복잡성 (사소하지 않은 경우 기본 분석 포함)

  • 코드의 문자 길이

  • 최종 계산 점수

이것은 나의 첫 번째 CodeGolf 질문이므로 위의 규칙에 실수 나 허점이 있다면 지적하십시오.


5
이것은 codegolf.stackexchange.com/questions/5977/… 과 매우 유사합니다 .
Gareth

2
1[\p:i.78498이것에 대한 나의 대답은 이것에 대한 나의 대답 이었다 1[\p:i.1000000. J의 내부 프라임 알고리즘이 O (n ^ 2)라고 가정하더라도 내 점수는 여전히 196입니다.
Gareth

2
아무도 그들의 복잡성을 제대로 계산하지 못하는 것 같습니다. n소수의 수 인지 최대 소수 인지에 대한 혼동 이 있으며 모든 사람들이 범위에 숫자를 더하는 0..n것이 O(logn)곱셈과 나눗셈이 더 비싸다 는 사실을 무시합니다 . 올바른 복잡성과 함께 몇 가지 예제 알고리즘을 제공하는 것이 좋습니다.
ugoren

3
k- 비트 수에 대해 현재 가장 잘 알려진 우선 순위 테스트는 O-tilde(k^6)입니다. 이것은 러닝 타임을 더 잘 주장하는 사람 O-tilde(n ln n (ln(n ln n))^6)이 문제의 일부를 잘못 이해 했다는 의미로 이어진다 . O-tilde채점에서 복잡성 을 어떻게 처리해야하는지에 대한 질문 .
피터 테일러

2
아무도 O (n)이 복잡성 항에서 O (kn) (상수 k)와 동일하지만 점수 항에서는 아님을 지적하지 않았습니다. 예를 들어, 복잡도가 O (n ^ 10)라고 가정합니다. 그것은 O (n ^ 10 * 1E-308)와 동일하며, 여전히 끔찍한 복잡성을 가진 거대한 프로그램으로 도전 할 수 있습니다.
JDL

답변:


10

Python (129 자, O (n * log log n), 점수 203.948)

나는 에라토스테네스의 체가 갈 길이라고 말하고 싶습니다. 매우 간단하고 비교적 빠릅니다.

N=15485864
a=[1]*N
x=xrange
for i in x(2,3936):
 if a[i]:
  for j in x(i*i,N,i):a[j]=0
print [i for i in x(len(a))if a[i]==1][2:]

이전부터 개선 된 코드.

파이썬 ( 191 개 156 152 문자, O (N * 로그 로그 N) (?), (252.620의 점수?))

나는 복잡성을 전혀 계산할 수 없으며 이것이 내가 줄 수있는 가장 좋은 근사치입니다.

from math import log as l
n=input()
N=n*int(l(n)+l(l(n)))
a=range(2,N)
for i in range(int(n**.5)+1):
 a=filter(lambda x:x%a[i] or x==a[i],a)
print a[:n]

n*int(l(n)+l(l(n)))소수 의 상단 경계 입니다 n.


1
복잡성 (따라서 점수) 계산은 상한을 기준으로 n하지만 소수는 아닙니다. 따라서 점수가 높아야한다고 가정합니다. 위의 내 의견을 참조하십시오.
Howard

상한 n? 그게 뭐야?
beary605

여기의 상한은 N=15485864입니다. 에 기반한 복잡도 계산 의 경우 소수의 밀도로 인해 n=1000000말할 수 있습니다 N=n*log(n).
ugoren

내 점수를 수정해야하는 경우 수정 해주세요. 점수 시스템에 대한 이해가 부족합니다.
beary605

@ beary605 첫 n 소수를 찾는 문제를 수정해도 괜찮습니까? 복잡성에 대한 많은 혼란과 n (O (f (n)))에 대한 많은 혼란을 해결할 것입니다
Optimus

7

Haskell, n ^ 1.1 경험적 성장률, 89 자, 139 점 (?)

다음은 사용하는 일반 라이브러리가 이전에로드 된 경우 GHCi 프롬프트에서 작동합니다. n 번째 소수, 1 기반 인쇄 :

let s=3:minus[5,7..](unionAll[[p*p,p*p+2*p..]|p<-s])in getLine>>=(print.((0:2:s)!!).read)

이것은 Eratosthenes의 무한한 체이며, 주문 된 목록을 위해 범용 라이브러리를 사용합니다. 소수와 소수 사이의 경험적 복잡성 O(n^1.1). 에 맞습니다 O(n*log(n)*log(log n)).

복잡성 추정 정보

100k 및 200k 프라임의 실행 시간을 측정 한 다음 계산하여을 logBase 2 (t2/t1)생성했습니다 n^1.09. 정의 g n = n*log n*log(log n), 계산 logBase 2 (g 200000 / g 100000)은 준다 n^1.12.

그런 다음 89**1.1 = 139, 비록 g(89) = 600. --- (?)

복잡도 함수 자체 대신 추정 성장률을 사용해야하는 것으로 보입니다. 예를 들어, g2 n = n*((log n)**2)*log(log n)보다 훨씬 낫지 n**1.5만 100 자에 대해 두 개의 점수는 각각 32391000입니다. 맞지 않아요 200k / 100k 범위에 대한 추정치는 logBase 2 (g2 200000 / g2 100000) = 1.2점수를 제공 100**1.2 = 251합니다.

또한 모든 소수를 인쇄하려고 시도하지 않고 대신 n 번째 소수를 인쇄하려고합니다 .

수입 금지, 240 자 n ^ 1.15 경험적 성장률, 546 점.

main=getLine>>=(print.s.read)
s n=let s=3:g 5(a[[p*p,p*p+2*p..]|p<-s])in(0:2:s)!!n
a((x:s):t)=x:u s(a$p t)
p((x:s):r:t)=(x:u s r):p t
g k s@(x:t)|k<x=k:g(k+2)s|True=g(k+2)t
u a@(x:r)b@(y:t)=case(compare x y)of LT->x:u r b;EQ->x:u r t;GT->y:u a t

5

하스켈, 72 89 자, O (n ^ 2), 점수 7921

숯불 당 가장 높은 점수가 이기는가? 첫 번째 N을 위해 수정되었습니다. 또한 계산기를 사용할 수 없으므로 내 점수가 생각보다 심하게 나쁘지 않습니다. (아래 소스에서 찾은 기본 시험 분할의 복잡성 사용).

윌 네스 아래 전체 하스켈 프로그램이 아닙니다 (실제로는 REPL에 의존). 다음은 의사 체 (pseudo-sieve)가있는보다 완전한 프로그램입니다 (수입품은 실제로 문자를 저장하지만 코드 골프에서는 수입품을 싫어합니다).

main=getLine>>= \x->print.take(read x).(let s(x:y)=x:s(filter((>0).(`mod`x))y)in s)$[2..]

이 버전은 의심 할 여지없이 (n ^ 2)입니다. 본 알고리즘은, '' '체'순진한 단지 골프 버전 여기 올드 ghci 1 라이너

getLine>>= \x->print.take(read x)$Data.List.nubBy(\x y->x`mod`y==0)[2..]

그것이 연결되는 라이브러리가 꽤 좋기 때문에 오래된 부정 행위를 떠나십시오.

print$take(10^6)Data.Numbers.Primes.primes

구현 및 시간 복잡성에 대한 링크는 여기 를 참조 하십시오 . 불행하게도 바퀴는 log (n) 조회 시간을 가지므로 요소가 느려지 게됩니다.


• 내장 기능이나 라이브러리를 통해 프라임을 생성 할 수 없음
beary605

@walpen 죄송합니다. 알림없이 규칙을 수정했습니다. 적합하다고 생각되는대로 변경하십시오
Optimus

복잡성이 O ((n ln n) ^ 1.5 ln (n ln n) ^ 0.585)와 같지 않습니까? (또는 O ((n ln n) ^ 1.5 ln (n ln n)) 하스켈이 가라 쓰바라고 가정 한 것처럼 순진한 분할을 사용하지 않는다면)
Peter Taylor

아니, 그것은 끔찍한 점수를 제공하기 때문에 : /. 하지만 당신 말이 옳아 요 그것은 시험 분열처럼 ​​보였고, 그것은 시험 분열의 시간 복잡성입니다 (아마도 잘못된 출처에 대한 나의 독해 독해에 따르면). 지금은 내 점수를 NaN이라고하겠습니다. 안전합니다.
walpen 2016 년

나는 (내 Haskell은 무시할 만하지 만 SML에서 어떻게 자연스럽게 할 수 있는지 알고 있습니다 ...) 당신은 작은 소수로만 시험 분할을하고 있다고 가정합니다.이 경우 P의 시험 분할은 O ( P ^ 0.5 / ln P) 나누기. 그러나 P에 k 비트가 있으면 나누기에 O (k ^ 1.585) (Karatsuba) 또는 O (k ^ 2) (naïve) 시간이 걸리고 길이 O (ln (nlg n) 개의 O (ln (nlg n)) 수를 거쳐야합니다. n lg n)) 비트.
피터 테일러

5

C #, 447 자, 바이트 452, 점수?

using System;namespace PrimeNumbers{class C{static void GN(ulong n){ulong primes=0;for (ulong i=0;i<(n*3);i++){if(IP(i)==true){primes++;if(primes==n){Console.WriteLine(i);}}}}static bool IP(ulong n){if(n<=3){return n>1;}else if (n%2==0||n%3==0){return false;}for(ulong i=5;i*i<=n;i+=6){if(n%i==0||n%(i+2)==0){return false;}}return true;}static void Main(string[] args){ulong n=Convert.ToUInt64(Console.ReadLine());for(ulong i=0;i<n;i++){GN(i);}}}}

scriptcs 변형, 381 자, 385 바이트, 점수?

using System;static void GetN(ulong n){ulong primes=0;for (ulong i=0;i<(n*500);i++){if(IsPrime(i)==true){primes++;if(primes==n){Console.WriteLine(i);}}}}public static bool IsPrime(ulong n){if(n<=3){return n>1;}else if (n%2==0||n%3==0){return false;}for(ulong i=5;i*i<=n;i+=6){if(n%i==0||n%(i+2)==0){return false;}}return true;}ulong n=Convert.ToUInt64(Console.ReadLine());for(ulong i=0;i<n;i++){GetN(i);}

scriptcs를 설치하면 실행할 수 있습니다.

추신 : 나는 이것을 Vim에 썼다. :D


2
불필요한 공백을 제거하여 일부 문자를 저장할 수 있습니다. 예를 들어 =<기호 주위에 공백을 넣을 필요는 없습니다 . 또한이 코드의 바이트와 문자에 차이가 있다고 생각하지 않습니다. 그것은 548 문자와 548 바이트입니다.
ProgramFOX

2
고마워, 이것이 나의 첫번째 CodeGolf입니다!
XiKuuKy

4

GolfScript (45 자, 점수는 ~ 7708)

~[]2{..3${1$\%!}?={.@\+\}{;}if)1$,3$<}do;\;n*

이것은 소수로 간단한 시험 분할을 수행합니다. Ruby의 최첨단 (예 : 1.9.3.0 사용) 근처에서 산술 연산이 Toom-Cook 3 곱셈을 사용하므로 시험 분할은 O (n ^ 1.465)이고 분할의 전체 비용은 O((n ln n)^1.5 ln (n ln n)^0.465) = O(n^1.5 (ln n)^1.965)†입니다. 그러나 GolfScript에서 요소를 배열에 추가하려면 배열을 복사해야합니다. 나는 프라임 목록을 새로운 프라임이 발견 될 때만 프라임 목록을 복사하도록 최적화했습니다 n. 각 복사 작업은 O(n)크기가 O(ln(n ln n)) = O(ln n)† 인 항목입니다 O(n^2 ln n).

그리고 이것이 남녀 학생들에게 GolfScript가 진지한 프로그래밍보다는 골프에 사용되는 이유입니다.

O(ln (n ln n)) = O(ln n + ln ln n) = O(ln n). 다양한 게시물에 댓글을 달기 전에 이것을 발견해야합니다 ...


4

텍스트 편집기로도 쉽게 할 수 있습니다!

Vim : 143 번의 키 입력 (115 개의 동작) : O (n ^ 2 * log (n)) : 점수 : 101485.21

제출:

qpqqdqA^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"ddmpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0qqpmp"aywgg@dqgg@p

입력 : N은 빈 문서의 첫 줄에 있어야합니다. 이 작업이 완료되면 2에서 N까지의 각 소수는 별도의 줄이됩니다.

명령 실행

먼저, 캐럿이 앞에있는 명령은 Ctrl 키를 누른 상태에서 다음 문자를 입력해야 함을 의미합니다 (예 : ^ V is Ctrl-v및 ^ R is Ctrl-r).

이것은 @a, @b, @d 및 @p 레지스터의 내용을 덮어 씁니다.

q명령을 사용하기 때문에 매크로에 배치 할 수 없습니다. 그러나 다음은이를 실행하기위한 몇 가지 팁입니다.

  • qpqqdq 그냥 레지스터를 지 웁니다.
  • A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"dd숫자 2에서 N + 1까지의 목록을 만듭니다. 이것은 두 주요 부분 사이의 휴식이므로 일단 완료되면 다시 할 필요가 없습니다.
  • mpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0qqpmp"aywgg@dqgg@p한 번에 입력해야합니다. 무언가를 망칠 수 있으므로 백 스페이스를 피하십시오.
    • 실수 qdqqpq한 경우이 줄을 다시 입력 하십시오.

큰 N의 경우 이것은 매우 느립니다. N = 5000을 실행하는 데 약 27 분이 걸렸습니다. 자신에게 경고를 고려하십시오.

연산:

소수를 찾는 데 기본 재귀 알고리즘을 사용합니다. 1과 A 사이의 모든 소수 목록이 주어지면 A + 1은 소수 목록의 숫자로 나눌 수없는 경우 소수입니다. A = 2에서 시작하여 발견 된대로 소수를 목록에 추가하십시오. N 재귀 후 목록에는 N까지의 모든 소수가 포함됩니다.

복잡성

이 알고리즘은 O (nN)의 복잡성을 가지며, 여기서 N은 입력 수이고 n은 최대 N까지의 소수입니다. 각 재귀는 n 개의 숫자를 테스트하고 N 개의 재귀는 O (nN)을 제공하여 수행됩니다.

그러나 N ~ n * log (n), 최종 복잡도는 O (n 2 * log (n)) ( https://en.wikipedia.org/wiki/Prime_number_theorem#Approximations_for_the_nth_prime_number )

설명

vim 명령에서 프로그램 흐름을 식별하는 것은 쉽지 않으므로 동일한 흐름에 따라 파이썬으로 다시 작성했습니다. Vim 코드와 마찬가지로 파이썬 코드는 끝에 도달하면 오류가 발생합니다. 파이썬은 재귀를 너무 좋아하지 않습니다. 이 코드를 N> 150 정도 사용하면 최대 재귀 수준에 도달합니다.

N = 20
primes = range(2, N+1)

# Python needs these defined.
mark_p = b = a = -1

# Check new number for factors. 
# This macro could be wrapped up in @d, but it saves space to leave it separate.
def p():
    global mark_d, mark_p, primes, a
    mark_d = 0
    print(primes)
    a = primes[mark_p]
    d()      

# Checks factor and determine what to do next
def d():
    global mark_d, mark_p, a, b, primes
    b = primes[mark_d]
    if(a == b): # Number is prime, check the next number
        mark_p += 1
        p()
    else:
        if(a%b == 0): # Number is not prime, delete it and check next number
            del(primes[mark_p])
            p()
        else: # Number might be prime, try next possible factor
            mark_d += 1
            d()

mark_p = 0 #Start at first number         
p()

이제 실제 키 입력을 분석하십시오!

  • qpqqdq@d 및 @p 레지스터를 지 웁니다. 이렇게하면 재귀 매크로를 설정할 때 아무것도 실행되지 않습니다.

  • A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"dd입력을 2에서 N + 1까지의 숫자 목록으로 바꿉니다. @d 매크로 설정의 부작용으로 N + 1 항목이 삭제됩니다.

    • 특히 숫자를 증가시키는 매크로를 작성하고 다음 줄에 복사 한 다음 1을 쓰고이 매크로를 N 번 실행합니다.
  • mpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0q위의 d () 함수를 구현하는 @d 매크로를 작성합니다. "If"문은 Vim에서 구현하기에 흥미 롭습니다. 검색 연산자 *를 사용하면 따라갈 특정 경로를 선택할 수 있습니다. 우리가 얻는 명령을 더 세분화

    • mpqd여기에 p 표시를 설정하고 @d 매크로 기록을 시작하십시오. p 마크를 설정해야합니다.
    • o^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc> if / else 문을 쓴다
    • 0*w*wyiWdd@0 실제로 if 문을 실행합니다.
    • 이 명령을 실행하기 전에 줄에 @a @b 0 0 `pj@p @a 0 (@a%@b) `pdd@p 0 `dj@d
    • 0 커서를 줄의 시작 부분으로 이동
    • *w*w 다음에 실행할 코드로 커서를 이동

      1. @a == @b 인 경우, 즉 @a `pj@p의 다음 숫자로 이동하여 @p를 실행합니다.
      2. @a! = @b 및 @ a % @ b == 0 인 경우, 즉 `pdd@p현재 숫자 @a를 삭제 한 후 다음 숫자에서 @p를 실행합니다.
      3. @a! = @b 및 @ a %% b! = 0 인 경우, 즉 `dj@d@b의 다음 숫자를 확인하여 @a의 인수인지 확인합니다.
    • yiWdd@0 명령을 0 레지스터로 yanks, 행을 삭제하고 명령을 실행

    • q @d 매크로의 기록을 종료합니다
  • 이것이 처음 실행될 때 `pdd@pN + 1 행을 삭제하면서 명령이 실행됩니다.

  • qpmp"aywgg@dq @p 매크로를 작성하여 커서 아래에 숫자를 저장 한 다음 첫 번째 항목으로 이동하여 @d를 실행합니다.

  • gg@p 실제로 @p를 실행하여 전체 파일을 반복합니다.


3

QBASIC, 98 문자, 복잡성 N Sqrt (N), 점수 970

I=1
A:I=I+2
FOR J=2 TO I^.5
    IF I MOD J=0 THEN GOTO A
NEXT
?I
K=K+1
IF K=1e6 THEN GOTO B
GOTO A
B:

문제 설명을 약간 수정했습니다. 이제 첫 번째 'n'소수를 찾습니다. 아무런 통지도 없습니다.
Optimus

이 프로그램에 대해 "소스 내"입력을 가정 할 수 있습니다. 즉, 입력은 바로 다음의 숫자입니다 IF K=(따라서 프로그램 길이는 숫자를 포함하지 않습니다). 프로그램 ?2은 그대로 시작 부분 에 추가 하고로 변경 K=...하여 수정할 수있는 2를 포함하지 않는 첫 번째 n 소수를 인쇄합니다 K=...-1. 프로그램은 또한 밖으로 공간을 고려하여 조금 golfed 수 J=2 TO, J=0 THEN, K=...-1 THEN및 들여 쓰기를 제거. 나는 이것이 96 문자 프로그램을 초래한다고 믿는다.
res

3

스칼라 263 자

새로운 요구 사항에 맞게 업데이트되었습니다. 코드의 25 %는 아래의 소수를 계산하기위한 합리적인 상한값을 찾는 데 사용됩니다.

object P extends App{
def c(M:Int)={
val p=collection.mutable.BitSet(M+1)
p(2)=true
(3 to M+1 by 2).map(p(_)=true)
for(i<-p){
var j=2*i;
while(j<M){
if(p(j))p(j)=false
j+=i}
}
p
}
val i=args(0).toInt
println(c(((math.log(i)*i*1.3)toInt)).take(i).mkString("\n"))
}

나도 체를 얻었다.

다음은 분석 비용을 계산하지 않은 계산 비용에 대한 경험적 테스트입니다.

object PrimesTo extends App{
    var cnt=0
    def c(M:Int)={
        val p=(false::false::true::List.range(3,M+1).map(_%2!=0)).toArray
        for (i <- List.range (3, M, 2)
            if (p (i))) {
                var j=2*i;
                while (j < M) {
                    cnt+=1
                    if (p (j)) 
                        p(j)=false
                    j+=i}
            }
        (1 to M).filter (x => p (x))
    }
    val i = args(0).toInt
    /*
        To get the number x with i primes below, it is nearly ln(x)*x. For small numbers 
        we need a correction factor 1.13, and to avoid a bigger factor for very small 
        numbers we add 666 as an upper bound.
    */
    val x = (math.log(i)*i*1.13).toInt+666
    println (c(x).take (i).mkString("\n"))
    System.err.println (x + "\tcount: " + cnt)
}
for n in {1..5} ; do i=$((10**$n)); scala -J-Xmx768M P $i ; done 

다음과 같은 계산으로 이어집니다.

List (960, 1766, 15127, 217099, 2988966)

점수를 계산하는 방법을 잘 모르겠습니다. 5자를 더 쓸 가치가 있습니까?

scala> List(4, 25, 168, 1229, 9592, 78498, 664579, 5761455, 50847534).map(x=>(math.log(x)*x*1.13).toInt+666) 
res42: List[Int] = List(672, 756, 1638, 10545, 100045, 1000419, 10068909, 101346800, 1019549994)

scala> List(4, 25, 168, 1229, 9592, 78498, 664579, 5761455, 50847534).map(x=>(math.log(x)*x*1.3)toInt) 
res43: List[Int] = List(7, 104, 1119, 11365, 114329, 1150158, 11582935, 116592898, 1172932855)

n이 클수록 해당 범위에서 계산이 약 16 % 감소하지만 점수 공식에 대해서는 당연한 요소를 고려하지 않습니까?

새로운 Big-O 고려 사항 :

1000, 10 000, 100 000 소수 등을 찾으려면 소수의 밀도에 대한 공식을 사용합니다.

따라서 1 ~ 6 => NPrimes (10 ^ i)의 값 i는 9399, 133768 ... 외부 루프의 횟수로 실행됩니다.

나는 1.01 대신에 1.5보다 높은 지수를 제안한 Peter Taylor의 의견을 통해이 O- 함수를 반복적으로 찾았습니다.

def O(n:Int) = (math.pow((n * math.log (n)), 1.01)).toLong

O : (n : 정수)

val ns = List(10, 100, 1000, 10000, 100000, 1000*1000).map(x=>(math.log(x)*x*1.3)toInt).map(O) 

ns : 목록 [긴] = 목록 (102, 4152, 91532, 1612894, 25192460, 364664351)

 That's the list of upper values, to find primes below (since my algorithm has to know this value before it has to estimate it), send through the O-function, to find similar quotients for moving from 100 to 1000 to 10000 primes and so on: 

(ns.head /: ns.tail)((a, b) => {println (b*1.0/a); b})
40.705882352941174
22.045279383429673
17.62109426211598
15.619414543051187
14.47513863274964
13.73425213148954

1.01을 지수로 사용하면 몫입니다. 카운터가 경험적으로 찾는 것은 다음과 같습니다.

ns: Array[Int] = Array(1628, 2929, 23583, 321898, 4291625, 54289190, 660847317)

(ns.head /: ns.tail)((a, b) => {println (b*1.0/a); b})
1.799140049140049
8.051553431205189
13.649578085909342
13.332251210010625
12.65003116535112
12.172723833234572

처음 두 값은 특이 치입니다. 왜냐하면 작은 값 (최대 1000)에 대한 추정 공식을 지속적으로 수정했기 때문입니다.

Peter Taylors의 제안 1.5는 다음과 같습니다.

245.2396265560166
98.8566987153728
70.8831374743478
59.26104390040363
52.92941829568069
48.956394784317816

이제 내 가치는 다음과 같습니다.

O(263)
res85: Long = 1576

그러나 나는 O 값을 관찰 된 값에 얼마나 가깝게 사용할 수 있는지 잘 모르겠습니다.


죄송합니다. 복잡도와 관련된 모호성을 줄이기 위해 문제 설명을 약간 변경했습니다 (솔루션이 많이 변경되지 않을 것이라고 확신합니다)
Optimus

이것은 소수로 효과적으로 시험 분할됩니다. 내부 루프를 통과하는 횟수는 O(M^1.5 / ln M)이며, 매번 O(ln M)작업 (추가)을 수행하므로 전체적으로 O(M^1.5) = O((n ln n)^1.5)입니다.
피터 테일러

^ 1.5 대신 ^ 1.02를 사용하면 def O(n:Int) = (math.pow((n * math.log (n)), 1.02)).toLong경험적으로 카운터에서 찾은 값에 훨씬 더 가깝습니다. 내 결과를 내 게시물에 삽입합니다.
사용자가 알 수 없음

3

루비 66 자, O (n ^ 2) 점수-4356

lazyRuby 2.0부터 사용할 1.0/0수 있으며 무한 범위를 얻는 멋진 트릭입니다.

(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j==0}}.take(n).to_a

1
다음과 같이 변경하여 하나의 문자를 면도 할 수 있습니다(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.take(n).to_a
Qqwy

또는 심지어 : (이것은 솔루션의 효율성을 떨어 뜨리지 만 상한 O (n²) 경계를 변경하지는 않습니다) (2..(1.0/0)).lazy.select{|i|(2..i).one?{|j|i%j<1}}.take(n).to_a. 이 두 문자를 더 면도합니다.
Qqwy

잘 변경하면 (2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.first(n)61 문자가 발생합니다.
Richie

2

루비, 84 자, 84 바이트, 점수?

이 부분은 아마도이 부분에 대해서는 약간 초보자 일 것입니다.하지만 재미있는 시간을 보냈습니다. f(프라임 발견)이 n원하는 프라임 수와 같아 질 때까지 반복 됩니다.

재미있는 부분은 각 루프마다 검사되는 숫자보다 2에서 1까지 작은 배열을 만듭니다. 그런 다음 배열의 각 요소를 원래 숫자와 요소의 계수로 매핑하고 결과가 0인지 확인합니다.

또한 점수를 매기는 방법을 모릅니다.

최신 정보

코드 압축 및 (완전히 임의의) 값 포함 n

n,f,i=5**5,0,2
until f==n;f+=1;p i if !(2...i).to_a.map{|j|i%j}.include?(0);i+=1;end

기발한

f, i = 0, 2
until f == n
  (f += 1; p i) if !(2...i).to_a.map{|j| i % j}.include?(0)
  i += 1
end

i += 1비트 및 until루프는 일종의 개선을위한 영역으로 나를 밖으로 점프하지만,이 트랙에 나는 일종의 붙어의입니다. 어쨌든, 생각하는 것은 재미있었습니다.


2

스칼라, 124 자

object Q extends App{Stream.from(2).filter(p=>(2 to p)takeWhile(i=>i*i<=p)forall{p%_!= 0})take(args(0)toInt)foreach println}

제곱근까지 간단한 시험 분할. 그러므로 복잡성은 O (n ^ (1.5 + epsilon))이어야합니다

124 ^ 1.5 <1381, 그래서 제 점수가 될까요?


1

Perl-94 자, O (n log (n))-점수 : 427

perl -wle '$n=1;$t=1;while($n<$ARGV[0]){$t++;if((1x$t)!~/^1?$|^(11+?)\1+$/){print $t;$n++;}}'

파이썬-113 자

import re
z = int(input())
n=1
t=1
while n<z:
    t+=1
    if not re.match(r'^1?$|^(11+?)\1+$',"1"*t):
        print t
        n+=1

1

AWK, 96 86 바이트

자막 : 엄마를 봐! 추가 및 일부 부기!

파일 fsoe3.awk:

{for(n=2;l<$1;){if(n in L)p=L[n]
else{print p=n;l++}
for(N=p+n++;N in L;)N+=p
L[N]=p}}

운영:

$ awk -f fsoe3.awk <<< 5
2
3
5
7
11
$ awk -f fsoe3.awk <<< 1000 | wc -l
1000

BASH, 133 바이트

파일 x.bash:

a=2
while((l<$1));do if((b[a]))
then((c=b[a]));else((c=a,l++));echo $a;fi;((d=a+c))
while((b[d]));do((d+=c));done
((b[d]=c,a++));done

운영:

$ bash x.bash 5
2
3
5
7
11
$ bash x.bash 1000 | wc -l
1000

프라임은 이미 발견 된 프라임이 "양의 정수 테이프"에서 점프하도록하여 계산됩니다. 기본적으로 그것은 일련의 에라토스테네스 체입니다.

from time import time as t

L = {}
n = 2
l = 0

t0=t()

while l<1000000:

        if n in L:
                P = L[n]
        else:
                P = n
                l += 1
                print t()-t0

        m = n+P
        while m in L:
                m += P
        L[m] = P

        n += 1

... 파이썬에서와 동일한 알고리즘 l이며, 소수 대신 -th 소수가 발견 된 시간을 출력 합니다.

출력 된 결과 gnuplot는 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

점프는 아마도 버퍼링 된 데이터를 디스크에 기록하기 때문에 파일 입출력 지연과 관련이있을 것입니다 ...

더 많은 수의 소수를 사용하면 게임에 추가 시스템 종속 지연이 발생합니다. 예를 들어 "양의 정수 테이프"를 나타내는 배열이 지속적으로 증가함에 따라 모든 컴퓨터가 더 많은 RAM (또는 이후 스왑)을 요구합니다.

... 그래서 실험 데이터를 보면서 복잡성에 대한 아이디어를 얻는 것은 실제로 많은 도움이되지 않습니다 ... :-(


이제 n소수 를 찾는 데 필요한 추가 사항을 계산합니다 .

cells = {}
current = 2
found = 0

additons = 0

while found < 10000000:

        if current in cells:
                candidate = cells[current]
                del cells[current] # the seen part is irrelevant
        else:
                candidate = current
                found += 1 ; additons += 1
                print additons

        destination = current + candidate ; additons += 1
        while destination in cells:
                destination += candidate ; additons += 1
        cells[destination] = candidate

        current += 1 ; additons += 1

여기에 이미지 설명을 입력하십시오


어떻게 그래프를 만들었습니까?
cat

1
Gnuplotset term xterm다음의 스크린 샷 xterm(잊혀진 기능에 아마 근처)의 그래픽 창. ;-)

0

스칼라 121 (99 개 주 보일러 보트 제외)

object Q extends App{Stream.from(2).filter{a=>Range(2,a).filter(a%_==0).isEmpty}.take(readLine().toInt).foreach(println)}

0

파이썬 3, 117106 바이트

이 솔루션은 숫자가 소수가 아닌 0을 출력하기 때문에 약간 사소하지만 어쨌든 게시 할 것입니다.

r=range
for i in[2]+[i*(not 0 in[i%j for j in r(3,int(i**0.5)+1,2)])for i in r(3,int(input()),2)]:print(i)

또한 알고리즘의 복잡성을 해결하는 방법을 잘 모르겠습니다. 이 때문에 공감하지 마십시오. 대신, 잘하고 내가 어떻게 해결할 수 있는지 의견을 말하십시오. 또한 어떻게 단축 할 수 있는지 알려주십시오.


난 당신이 넣을 수 있다고 생각 print(i)루프에 대한 같은 줄에와있는 공백을 제거 in [2], 0 if, 0 in [i%j+1,2)] else.
acrolith

@daHugLenny 와우, 정말 고마워! 내 게시물을 몇 초 안에 편집하겠습니다. :-D
0WJYxW9FMN

@daHugLenny 우연히 효율성을 계산하는 방법을 알고 있습니까?
0WJYxW9FMN

아니요, 죄송합니다. (댓글은 15 자 이상이어야합니다)
acrolith

어쨌든 고마워 내 프로그램을 가장 짧은 프로그램으로 만들었습니다!
0WJYxW9FMN


0

Perl 6, 152 바이트, O (n log n log (n log n) 로그 (log (n log n))) (?), 9594.79 점

이 페이지 에 따르면 , n까지의 모든 소수를 찾는 비트 복잡도는 O (n log n log log n)입니다. 위의 복잡성은 n 번째 소수가 n log n에 비례한다는 사실을 사용합니다.

my \N=+slurp;my \P=N*(N.log+N.log.log);my @a=1 xx P;for 2..P.sqrt ->$i {if @a[$i] {@a[$_*$i]=0 for $i..P/$i}};say $_[1] for (@a Z ^P).grep(*[0])[2..N+1]

자격이없는 경우 Wentel에서 자격을 얻으려면
noɥʇʎԀʎzɐɹƆ

용서하지만 무슨 뜻인가요?
bb94

현상금 (fiiiiiiiiilerrrrr)
noɥʇʎԀʎzɐɹƆ

0

그루비 (50 바이트)-O (n * sqrt (n))-353.553390593

{[1,2]+(1..it).findAll{x->(2..x**0.5).every{x%it}}​}​

n을 취하고 1부터 n까지의 모든 숫자를 소수로 출력합니다.

내가 선택한 알고리즘은 소수 소수 n> 2 만 출력하므로 처음에 1,2를 추가해야합니다.

고장

x%it -나눌 수 없으면 암시 적 진실, 거짓이면 거짓.

(2..x**0.5).every{...}-2에서 sqrt (x) 사이의 모든 값에 대해 나눌 수 없는지 확인하십시오.이 값이 true를 리턴하려면 모든마다 true를 리턴해야합니다 .

(1..it).findAll{x->...} -1과 n 사이의 모든 값에 대해 2와 sqrt (n) 사이에서 나눌 수없는 기준에 맞는 모든 것을 찾으십시오.

{[1,2]+...}​ -항상 소수이고 알고리즘에 포함되지 않으므로 1과 2를 추가하십시오.


0

라켓 155 바이트

(let p((o'(2))(c 3))(cond[(>=(length o)n)(reverse o)][(ormap(λ(x)(= 0(modulo c x)))
(filter(λ(x)(<= x(sqrt c)))o))(p o(add1 c))][(p(cons c o)(add1 c))]))

찾은 소수의 목록을 유지하고 이미 찾은 소수로 다음 각 숫자의 분할 성을 검사합니다. 또한 테스트가 완료된 수의 제곱근까지만 검사합니다.

언 골프 드 :

(define(nprimes n)
  (let loop ((outl '(2))                   ; outlist having primes being created
             (current 3))                  ; current number being tested
  (cond
    [(>= (length outl) n) (reverse outl)]  ; if n primes found, print outlist.
    [(ormap (λ(x) (= 0 (modulo current x))) ; test if divisible by any previously found prime
            (filter                         ; filter outlist till sqrt of current number
             (λ(x) (<= x (sqrt current)))
             outl))
     (loop outl (add1 current)) ]           ; goto next number without adding to prime list
    [else (loop (cons current outl) (add1 current))] ; add to prime list and go to next number
    )))

테스트 :

(nprimes 35)

산출:

'(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149)

0

awk 45 (복잡성 N ^ 2)

다른 awk, 최대 100까지의 소수는 이와 같이 사용하십시오.

awk '{for(i=2;i<=sqrt(NR);i++) if(!(NR%i)) next} NR>1' <(seq 100)

코드 골프 카운트 부분은

{for(i=2;i<=sqrt(NR);i++)if(!(NR%i))next}NR>1

스크립트 파일에 넣고 다음과 같이 실행할 수 있습니다. awk -f prime.awk <(seq 100)


0

자바 스크립트, 61 자

f=(n,p=2,i=2)=>p%i?f(n,p,++i):i==p&&n--&alert(p)||n&&f(n,++p)

O (n ^ 2)보다 약간 나쁘면 큰 n에 대한 스택 공간이 부족합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.