길이, 합계 및 곱이 소수 인 가장 큰 소수를 찾습니다.


37

숫자 113는 길이 3가 소수이고 디지털 합계 5 = 1 + 1 + 3가 소수이며 디지털 제품 3 = 1 * 1 * 3이 소수 인 첫 번째 소수입니다 .

이 3 가지 속성을 가진 소수를 최상 이라고 합니다. 소수 111171111151다른 예입니다.

괜찮은 수준의 현대 개인용 컴퓨터 (예 : 여기 에서 선호하는 사양 ) 에서 1 시간 이내에 가능한 가장 큰 소수를 찾을 수있는 프로그램을 작성 하십시오 .

당신은 단순히 우리에게 큰 최고의 프라임을 제공해서는 안됩니다. 실제로 작동하는 코드로 검색 프로세스를 보여 주어야합니다. 귀하 또는 다른 사람들의 솔루션을 구축 할 수는 있지만 크레딧을 제공해야합니다. 우리는 보통 한 시간 안에 일반 컴퓨터에서 실현할 수있는 가장 큰 최고의 소수를 찾으려고 노력하고 있습니다.

채점

가장 큰 최고 수상을 발견 한 제출물이 이깁니다. 최고 프라임 프라임이 무한히 많다는 것이 밝혀지면 최고 프라임 프라임이 가장 먼저 생성됩니다.

(만약 당신이 무한한 많은 소수를 가지고 있지 않다는 것을 수학적으로 증명할 수 있다면 나는 단지 당신에게 200 현상금 담당자를 줄 것입니다. :))

세부

  • 인터넷 (예 : 인터넷)을 생성하기 위해 모든 소스를 사용할 수 있습니다.
  • 확률 적 주요 테스트 방법을 사용할 수 있습니다.
  • 모든 것은 기본 10에 있습니다.
  • 0과 1은 소수로 간주되지 않습니다.
  • 포함 된 프라임 0의 디지털 제품은 0분명히 최고가 될 수 없습니다.
  • 페이지를 덜 복잡하게 유지하려면 큰 (100+ 숫자) 최고 소수를 다음과 같은 형식으로 넣으십시오.

    {[number of 1's before the prime digit]}[prime digit]{[number of 1's after the prime digit]}
    

    따라서 1111151로 표현 될 수 있습니다 {5}5{1}.


프라임 목록으로 시작하거나 인터넷에서 목록을 가져 와서 최고점 확인 시간을 보낼 수 있습니까?
Sparr

2
가장 높은 최고 수상으로 시작할 수 있다면 이것은 두 최고 수상 사이의 가장 큰 격차에 걸쳐 정확히 한 시간을 소비하는 프로그램을 작성할 수있는 사람에게 도전이됩니다. :(
Sparr

8
0을 포함하지 않는 것 외에도, 잠재적 인 최고 프라임은 분명히 1 ^ n [3 | 5 | 7] 1 ^ m 형식이어야합니다. 즉, 일부 1, 10 이하 및 1 이상의 소수입니다. 더 많은 제약이 있습니다.
Ingo Bürk

3
Ryan은 MSE 에 대해 무한히 많은 최고의 소수의 존재 관한 질문을 시작했습니다 . 그 질문에 대한 통찰력이 있다면, 무게를 측정하십시오!
Semiclassical

1
나는 현재 무한한 수의 최고 소수에 대한 증거가 없다는 것을 쉽게 알 수 있습니다 (그리고 상당한 양의 작업이 진행되었습니다). michaelnielsen.org/polymath1/… 에 따르면 , 소수는 246 개의 작은 간격으로 무한대로 나옵니다. 그러나 무한 최고 소수를 증명하려면 2, 4 또는 6의 간격이 필요합니다. 어딘가에 3, 5 또는 7).
Tim S.

답변:


9

Perl, 15101 자리, {83} 7 {15017}, 8 분 찾은 최대 : 72227 자리

내 모듈 Math :: Prime :: UtilGMP 백엔드 사용 . 그것은 포함 compositeness 테스트의 숫자가 is_prob_prime () 배아 줄기 BPSW 테스트 (PARI의 ispseudoprime보다 약간 더 엄격한)와 is_prime () 한 랜덤 기본 MR 및 추가 is_provable_prime () BLS75 T5 또는 ECPP를 실행합니다. 이러한 크기와 유형에서 증명을 수행하는 데 시간이 오래 걸립니다. 나는 pedantic verifier sub에 또 다른 MR 테스트를 던졌습니다. 확실히 가장 빠른 컴퓨터가 아닌 Core2 E7500의 시간 (내 i7-4770K에서 2.5 분이 걸립니다).

Tim S.가 지적했듯이 단일 테스트에 1 시간이 걸리는 지점까지 더 큰 값을 계속 검색 할 수 있습니다. 이 E7500의 ~ 15000 자리에서 MR 테스트의 경우 약 26 초가 걸리고 전체 is_prime의 경우 2 분이 걸립니다 (시험 분할 + 기본 2 MR + ES Lucas + 1 개의 임의 기본 MR). i7-4770K가 3 배 이상 빠릅니다. 나는 주로 다른 사람들의 결과에 어떤 영향을 미치는지 보며 몇 가지 크기를 시도했습니다. 나는 8k, 20k 및 16k를 시도하여 ~ 5 분 후에 각각을 죽였습니다. 그런 다음 ~ 10m마다 15k를 진행하려고 시도하고 네 번째 것에 운이 좋았습니다.

OpenPFGW의 PRP 테스트는 4000이 넘는 숫자를 지나면 확실히 빠르며 실제로 50k + 범위에서 훨씬 빠릅니다. 그러나이 테스트에는 상당한 양의 오 탐지 (false positive)가있어 사전 테스트가 잘 이루어 지지만 다른 결과로 결과를 확인하고 싶습니다.

이것은 펄 스레드 또는 모듈의 병렬 피보나치 프라임 파인더 예제와 유사한 MCE를 사용하여 병렬화 될 수 있습니다.

단일 코어를 사용하여 유휴 i7-4770K의 타이밍 및 결과 :

  • 입력 3000, 16 초, 3019 자리, {318} 5 {2700}
  • 입력 4000, 47 초, 4001 자리, {393} 7 {3607}
  • 입력 4100, 5 초, 4127 자리, {29} 7 {4097}
  • 입력 6217, 5 초, 6217 자리, {23} 5 {6193}
  • 입력 6500, 5 분, 6547 자리, {598} 5 {5948}
  • 입력 7000, 15 분, 7013 자리, {2411} 7 {4601}
  • 입력 9000, 11 분, 9001 자리, {952} 7 {8048}
  • 입력 12000, 10 분, 12007 자리, {652} 5 {11354}
  • 입력 15100, 2.5 분, 15101 자리, {83} 7 {15017}
  • 입력 24600, 47 분, 24671 자리, {621} 7 {24049}
  • 입력 32060, 18 분, 32063 자리, {83} 7 {31979}
  • 입력 57000, 39 분, 57037 자리, {112} 5 {56924}
  • 입력 72225, 42 분, 72227 자리, {16} 3 {72210}

32k 자리 결과의 경우, 32000에서 시작하는 연속 인수로 각각 6 개의 스크립트를 동시에 실행했습니다. 26.5 분 후 하나는 32063 자리 결과로 끝났습니다. 57k의 경우 57k 결과가 57 분에 반환 될 때까지 연속 스크립트가 한 번에 6 시간 씩 500 씩 입력 증분으로 실행되도록했습니다. 72k 자리 결과는 70k에서 연속적인 소수를 수행하여 발견되었으므로 한 시간 안에는 찾을 수 없습니다 (처음부터 어디에서 시작해야하는지 알 수 있습니다).

스크립트 :

#!/usr/bin/env perl
use warnings;
use strict;
use Math::Prime::Util qw/:all/;
use Math::Prime::Util::GMP;  # Just to ensure it is used.

my $l = shift || 1000;  $l--;

while (1) {
  $l = next_prime($l);
  my @D = grep { is_prime($l-1 + $_) } (3,5,7);
  next unless scalar @D > 0;
  for my $s (0 .. $l-1) {
    my $e = $l-$s-1;
    warn "   checking $l $s\n" unless $s % 100;
    for my $d (@D) {
      my $n = "1"x$s . $d . "1"x$e;
      die unless length($n) == $l;
      verify_supreme($n,$s,$d,$e) if is_prime($n);  # ES BPSW + 1 rand-base M-R
    }
  }
}
sub verify_supreme {  # Be pedantic and verify the result
  my($n,$s,$d,$e) = @_;
  die "Incorrect length" unless is_prime(length($n));
  die "Incorrect sum" unless is_prime(vecsum(split(//,$n)));
  my $prod = 1; $prod *= $_ for split(//,$n);
  die "Incorrect product" unless is_prime($prod);
  die "n is not a prime!" unless miller_rabin_random($n,1);  # One more M-R test
  die "{$s} $d {$e}\n";
}

이 라이브러리를 소개해 주셔서 +1! 반복 내 컴퓨터에 타이밍 미만 10 ^ 7 (CPython과에 비해 소수가 gmpy2, 그리고 PyPy과 my_math) : codepad.org/aSzc0esT
프리모

당신이 그것을 좋아해서 다행입니다! forprimes { ...do stuff... } 1e7;10 배 이상 빠른 방법을 포함하여 다른 방법이 있습니다 (많은 훌륭한 아이디어를 위해 Pari / GP로 권장). 항상 의견을 보내 주셔서 감사합니다. 원하는 방식으로 작동하지 않는 경우 알려주십시오.
DanaJ

21

PyPy의 Python 2.7, {2404} 3 {1596} (~ 10 ^ 4000)

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111113111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

4000에서 시작한 후 약 50 분 후에이 코드를 찾았습니다. 따라서 이것이이 코드 접근 방식의 상한이라고 생각합니다.

변경 : 일부 길이는 다른 소수보다 이러한 종류의 소수를 생성하는 것이 더 유익한 것으로 나타 났으므로 이동하기 전에 가능한 모든 위치 대신 1이 아닌 임의의 숫자로 된 50 개의 임의 위치 만 확인하기로 결정했습니다. 의 위에. 이것이 성능을 향상 시킬지 확실하지는 않지만 50이 정확하다는 것을 알 수 있습니다.

가능성리스트는 제품 요구 사항이 충족 되려면 소수를 제외한 소수 여야한다는 사실을 기반으로 생성됩니다. 또한 합계와 길이 관계로 인해 소수는 2가 될 수 없으며 디지털 합계를 3으로 나눌 수 없어 % 3 요구 사항이 발생합니다.

@primo가 작성한 http://codepad.org/KtXsydxK 에서 가져온 is_prime

참고 :이 is_prime 함수는 실제로 Baillie-PSW 의사 프라임 테스트이지만 알려진 카운터 예제는 없으므로 구별에 대해 걱정하지 않을 것입니다.

#http://codepad.org/KtXsydxK
from my_math import is_prime
import time,random
LLIMIT=2748
time.clock()
start_time=time.time()
checked=0
while time.time()-start_time<3600:
    small_primes = [a for a in range(LLIMIT,2*LLIMIT) if is_prime(a)]
    leng,dig=(0,0)
    for a in small_primes:
        if a+2 in small_primes:
            leng,dig=(a,3)
            break
        if a+4 in small_primes:
            leng,dig=(a,5)
            break
        if a+6 in small_primes:
            leng,dig=(a,7)
            break
    start=time.clock()
    print leng,dig,time.clock(),checked
    for loc in random.sample(range(leng),50):
        checked+=1
        if is_prime(int('1'*loc+str(dig)+'1'*(leng-loc-1))):
            print leng-1,loc,dig,time.clock(),time.clock()-start, \
                  int('1'*loc+str(dig)+'1'*(leng-loc-1))
            break
    LLIMIT=leng+1

안타깝게도 나는 그 링크 외에는 아무것도 모른다. 나는 여기에 링크를 발견했다 : codegolf.stackexchange.com/questions/10739/… 첫 번째 답변
isaacg

그럼 내가 신용 할게
isaacg

10
그것은 월리가있는 ASCII와 같습니다 ...
trichoplax

5
아마도 당신은 함수의 이름을 바꿔야 할 것입니다 is_very_very_very_very_very_very_very_probably_prime()...
trichoplax

2
MathmaticaMaple은 모두 같은 방법을 사용하므로 그렇게 나쁘지는 않습니다.
primo

13

PARI / GP, 4127 자리

(10 4127-1 ) / 9 + 2 * 10515

이것은 매우 간단한 검색입니다. 소수 자릿수 만 확인한 다음 사용할 수있는 소수를 계산 한 다음 모든 가능성을 반복하십시오. 사용할 소수 또는 소수의 적절한 소수가있는 일반적인 경우를 특별하게 정리했습니다.

supreme(lim,startAt=3)={
    forprime(d=startAt,lim,
        my(N=10^d\9, P=select(p->isprime(d+p),[1,2,4,6]), D, n=1);
        if(#P==0, next);
        if(#P==1,
            for(i=0,d-1,
                if (ispseudoprime(D=N+n*P[1]), print(D));
                n*=10
            );
            next
        );
        D=vector(#P-1,i,P[i+1]-P[i]);
        for(i=0,d-1,
            forstep(k=N+n*P[1],N+n*P[#P],n*D,
                if (ispseudoprime(k), print(k))
            );
            n*=10
        )
    )
};
supreme(4200, 4100)

상당히 오래된 머신의 한 코어에서 계산하는 데 36 분이 걸렸습니다. 한 시간에 5000 자리 이상의 소수를 찾는 데 어려움이 없을 것입니다.

더 나은 해결책은 합리적인 언어를 사용하여 가장 안쪽 루프를 제외한 모든 작업을 수행 한 다음 특정 종류의 계산에 최적화 된 Primeform에 대한 abc 파일을 구성하는 것입니다. 이를 통해 계산을 10,000 자리 이상으로 푸시 할 수 있어야합니다.

편집 : 위에서 설명한 하이브리드 솔루션을 구현했지만 이전 컴퓨터에서 1 시간 이내에 10,000 자리를 초과하는 첫 번째 용어를 찾을 수 없습니다. 빠른 속도로 달리지 않는 한 덜 고상한 대상으로 변경해야합니다.


4100에서 시작하는 것을 어떻게 알았습니까?
isaacg

@isaacg : 나는 4000 개가 넘는 (잘못된) Mathematica 솔루션보다 더 크게하려고 노력했습니다. 나는 'No-up-my-sleeve'숫자로 100의 다음 배수로갔습니다. 실제로 소수를 찾는 데 예상보다 오래 갔고 (Mathematica보다 더 길어야 했으므로) 불행한 출발점이었던 것 같습니다.
Charles

아니, 실제로, 당신은 엄청나게 운이 좋았습니다. (4127,3)은 4100 이후 첫 번째 쌍이며, 우연히도 소수입니다. 많은 쌍이 전혀 소수가 아닙니다.
isaacg

@isaacg : 아마도. 주어진 쌍에서 소수를 찾을 확률이 ~ 80 %이므로 1-exp (-15 / (4 * log 10))이지만 휴리스틱은 명확하지 않습니다. 크기의 임의의 {2, 3, 5}-매끄러운 숫자처럼 행동하지 마십시오 (계산을 방해하지 않는 한).
Charles

@isaacg : 어쨌든 내가 지금 언급 한 "더 나은 솔루션"을 위해 노력하고 있습니다. 아무것도 발견하지 않고 10 ^ 10000 위의 처음 20 쌍을 검색했지만 ~ 15 분 밖에 걸리지 않았습니다.
Charles

7

Mathematica 3181 자리

업데이트 : 첫 번째 제출에 심각한 실수가있었습니다. 이 결과를 확인하는 데 시간을 할애 할 수있었습니다. 출력은 자릿수 목록으로 형식화됩니다. 따라서 각 조건을 쉽게 확인할 수 있습니다.

f[primeDigitLength_]:=
Module[{id=ConstantArray[1,primeDigitLength-1]},
permutations=Reverse@Sort@Flatten[Table[Insert[id,#,pos],{pos,primeDigitLength}]&/@{3,5,7},1];
Flatten[Select[permutations,PrimeQ[FromDigits[#]]\[And]PrimeQ[Plus@@#]&,1],1]]

이것은 첫 번째 테스트였으며 3181 자리수의 솔루션을 검색했습니다. 26 초 만에 첫 번째 사건을 발견했습니다.

추론을 봅시다. 그런 다음 프로그램 자체로 들어갑니다.

"450 번째 소수는 무엇입니까?"와 같이 시작하겠습니다. 숫자가 많은 솔루션 (3181)을 찾을 수 있습니까?

primeDigits = Prime[450]

3181


숫자는 숫자를 결합하여 찾습니다.

number = FromDigits[digits];

그러나 숫자를 표시하는 대신 숫자가 무엇이고 어디에 있는지 물어볼 수 있습니다.

DigitCount[number]

{3180, 0, 0, 0, 0, 0, 1, 0, 0, 0}

이는 숫자 1의 3180 인스턴스와 숫자 7의 단일 인스턴스가 있음을 의미합니다.

숫자 7은 어느 위치에 있습니까?

Position[digits, 7][[1, 1]]

142

숫자 7은 142 번째 숫자입니다. 다른 모든 것은 1입니다.


물론, 숫자의 곱은 소수, 즉 7이어야합니다.

digitProduct = Times @@ digits

7


그리고 숫자의 합계도 소수입니다.

digitSum = Plus @@ digits
PrimeQ[digitSum]

3187
맞다


그리고 우리는 자릿수가 소수입니다. 우리는 450 번째 소수 즉 3118을 선택했음을 기억하십시오.

모든 조건이 충족되었습니다.


3
내가 실수하지 않으면 그 합계는 4009이며 소수는 아닙니다.
gerw

한 가지 : 소수 자릿수가 아닌 소수 자릿수의 합계가 아니어야합니까? 귀하의 경우 4002 * 1 + 7 = 4009사양에 따라 4003이 아닌 테스트 해야합니다.
Johnride

2
@Johnride : 둘 다 소수 여야합니다.
gerw

@gerw가 맞습니다. 자릿수와 자릿수 및 자릿수는 모두 소수 여야합니다.
Calvin 's Hobbies

당신은 모두 맞았습니다. 이전 제출에서 나는 숫자의 합계가 초기인지 확인하는 것을 잊었다. 이제는 다음 중 하나 (중요하지 않은)가 소수인지 여부를 확인하여 수행합니다 : 숫자 길이 +2, 숫자 길이 _4 또는 숫자 길이 +6.
DavidC

7

Python 2.7, 6217 자리 : {23} 5 {6193} 6 분 51 초

나는 내 자신의 버전으로 작업하고 있었고 @issacg가 is_ (very_probably) _prime ()에도 불구하고 매우 비슷한 접근법으로 펀치를 얻었음을 알게되어 실망했습니다. 그러나 짧은 시간에 더 나은 답변을 얻는 중요한 차이점이 있음을 알았습니다 (is_prime을 사용할 때). 이를 분명히하기 위해 4000에서 시작할 때 PyPy가 아닌 표준 Python 인터프리터 (버전 2.7)를 사용하여 37 분만 26 분만에 더 나은 4001 자리 답변 ({393} 7 {3607})에 도달 합니다. 번역. 또한 숫자를 확인하는 '현장'이 아닙니다. 모든 후보자가 확인됩니다.

주요 개선 사항은 다음과 같습니다.

  1. 프라임 생성기 ( https://stackoverflow.com/questions/567222/simple-prime-generator-in-python/568618#568618 )를 사용하여 확인할 프라임 목록을 작성하고 (그의 "작은 프라임"버전) 적격 한 수의 길이를 생성합니다.

  2. 우리는 주어진 길이의 최대 최고 소수를 찾는 데 시간을 보내고 싶습니다. 그래서 가장 작은 것이 아니라 확인하기 위해 가능한 가장 큰 숫자를 먼저 구성합니다. 그런 다음 발견되면 즉시 다음 길이로 이동할 수 있습니다.

편집 : 이제 멀티 프로세싱

이것은 이전 버전의 중요한 변경 사항입니다. 전에는 8 코어 머신이 제대로 작동하지 않는다는 것을 알았으므로 파이썬에서 멀티 프로세싱을 처음 시도했습니다. 결과는 매우 좋습니다!

이 버전에서는 7 개의 자식 프로세스가 생성되어 잠재적 인 대기열 (num_length + 적격 숫자)에서 '작업'을 가져옵니다. 그들은 하나를 찾을 때까지 다른 [7,5,3] 포지션을 시도하는 것을 통해 이탈했다. 그렇다면 마스터 프로세스에 발견 된 가장 긴 새로운 길이를 알려줍니다. 아이들이 더 짧은 num_length에서 작업하는 경우, 보석을 내고 다음 길이를 얻습니다.

나는 6000 으로이 실행을 시작했지만 여전히 실행 중이지만 지금까지 결과에 매우 만족합니다.

이 프로그램은 아직 제대로 멈추지 않았지만 나에게는 큰 도움이되지 않았습니다.

이제 코드 :

#!/usr/bin/env python
from __future__ import print_function

import sys
from multiprocessing import Pool, cpu_count, Value
from datetime import datetime, timedelta

# is_prime() et al from: http://codepad.org/KtXsydxK - omitted for brevity
# gen_primes() from: https://stackoverflow.com/questions/567222/simple-prime-generator-in-python/568618#568618 - ommitted for brevity
from external_sources import is_prime, gen_primes


def gen_tasks(start_length):
    """
    A generator that produces a stream of eligible number lengths and digits
    """
    for num_length in gen_primes():
        if num_length < start_length:
            continue

        ns = [ n for n in [7,5,3] if num_length + n - 1 in prime_list ]
        if ns:
            yield (num_length, ns)


def hunt(num_length, ns):
    """
    Given the num_length and list of eligible digits to try, build combinations
    to try, and try them.
    """

    if datetime.now() > end_time or num_length <= largest.value:
        return

    print('Tasked with: {0}, {1}'.format(num_length, ns))
    sys.stdout.flush()
    template = list('1' * num_length)
    for offset in range(num_length):
        for n in ns:
            if datetime.now() > end_time or num_length <= largest.value:
                return

            num_list = template[:]
            num_list[offset] = str(n)
            num = int(''.join(num_list))

            if is_prime(num):
                elapsed = datetime.now() - start_time
                largest.value = num_length
                print('\n{0} - "{1}"\a'.format(elapsed, num))


if __name__ == '__main__':
    start_time = datetime.now()
    end_time = start_time + timedelta(seconds=3600)

    print('Starting @ {0}, will stop @ {1}'.format(start_time, end_time))

    start_length = int(sys.argv[1])

    #
    # Just create a list of primes for checking. Up to 20006 will cover the first
    # 20,000 digits of solutions
    #
    prime_list = []
    for prime in gen_primes():
        prime_list.append(prime)
        if prime > 20006:
            break;
    print('prime_list is primed.')

    largest = Value('d', 0)

    task_generator = gen_tasks(start_length)

    cores = cpu_count()
    print('Number of cores: {0}'.format(cores))


    #
    # We reduce the number of cores by 1 because __main__ is another process
    #
    pool = Pool(processes=cores - 1)

    while datetime.now() < end_time:
        pool.apply_async(hunt, next(task_generator))

당신이로 codepad 링크를 나타낼 경우 더 명확하게 읽을 것 [깨진 필요한 경우] 수입
Sparr

다른 쪽의 코드는 실제로 그렇게 가져올 수 없기 때문에 혼란 스러울 것이라고 생각합니다.
mkoistinen

isaacg의 구문을 사용하십시오. , URL을 언급 한 후 (자신의 경우, my_math) 존재하지 않는 패키지에서 가져
Sparr

1
실제로, 나는 또한 가장 큰 숫자에서 가장 작은 숫자를 생성합니다. 코드 차이가 크게 중요하지 않다고 생각합니다. 차이점은 코드보다 컴퓨터에 더 많이있을 것으로 기대합니다. 그럼에도 불구하고, 잘하고 사이트에 오신 것을 환영합니다.
isaacg

my_math프라임 목록을 생성하는데도 사용할 수 있습니다 while prime < 20006: prime = next_prime(prime). 보다 약 3 배 빠르며 gen_primes훨씬 더 효율적인 메모리 인 것 같습니다.
primo

6

C, GMP는 - {7224} 5 {564} 7789 =

@issacg와 여러분 모두에게 영감과 요령을 알려주십시오.
또한이 질문에 대한 훌륭한 질문 asker @ Calvin 's Hobbies도 있습니다.

엮다: gcc -I/usr/local/include -o p_out p.c -pthread -L/usr/local/lib -lgmp

계산 능력을 기부하거나 성능이 궁금하다면 코드를 자유롭게 복사하고 컴파일하십시오. ;) GMP가 설치되어 있어야합니다.

#include<stdio.h>
#include<stdlib.h>
#include<sys/time.h>
#include<gmp.h>
#include<pthread.h>

#define THREAD_COUNT 1
#define MAX_DIGITS   7800
#define MIN_DIGITS   1000

static void huntSupremePrime(int startIndex) {

    char digits[MAX_DIGITS + 1];

    for (int i = 0; i < MAX_DIGITS; digits[i++] = '1');

    digits[MAX_DIGITS] = '\0';
    mpz_t testPrime, digitSum, digitCount, increment;

    for (int j = 0; j < MAX_DIGITS - startIndex; digits[j++] = '0');

    int step = THREAD_COUNT * 2;

    for (int i = startIndex, l = MAX_DIGITS - startIndex; i > MIN_DIGITS - 1; 
        i -= step, l += step) {
        fprintf(stderr, "Testing for %d digits.\n", i);
        mpz_init_set_ui(digitCount, i);
        if (mpz_millerrabin(digitCount, 10)) {
            for (int j = 3; j < 8; j += 2) {
                mpz_init_set_ui(digitSum, i - 1 + j);
                if (mpz_millerrabin(digitSum, 10)) {
                    gmp_printf("%Zd \n", digitSum);
                    digits[MAX_DIGITS - 1] = j + 48;
                    mpz_init_set_str(testPrime, digits, 10);
                    mpz_init_set_ui(increment, (j - 1) * 99);
                    for (int k = 0; k < i/20; ++k) {
                        if (mpz_millerrabin(testPrime, 25)) {
                            i = 0;
                            j = 9;
                            k = l;
                            gmp_printf("%Zd\n", testPrime);
                            break;
                        }
                        mpz_add(testPrime, testPrime, increment);
                        mpz_mul_ui(increment, increment, 100);
                        fprintf(stderr, "TICK %d\n", k);
                    }

                }
            }
        }
        for (int j = 0; j < step; digits[l + j++] = '0');

    }
}

static void *huntSupremePrimeThread(void *p) {
    int* startIndex = (int*) p;
    huntSupremePrime(*startIndex);
    pthread_exit(NULL);
}

int main(int argc, char *argv[]) {

    int  startIndexes[THREAD_COUNT];
    pthread_t threads[THREAD_COUNT];

    int startIndex = MAX_DIGITS;
    for (int i = 0; i < THREAD_COUNT; ++i) {
        for (;startIndex % 2 == 0; --startIndex);
        startIndexes[i] = startIndex;
        int rc = pthread_create(&threads[i], NULL, huntSupremePrimeThread, (void*)&startIndexes[i]); 
        if (rc) { 
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }
        --startIndex;
    }

    for (int i = 0; i < THREAD_COUNT; ++i) {
        void * status;
        int rc = pthread_join(threads[i], &status);
        if (rc) {
            printf("ERROR: return code from pthread_join() is %d\n", rc);
            exit(-1);
        }
    }

    pthread_exit(NULL);
    return 0;
}

5

PFGW, 6067 자리, {5956} 7 {110}

실행 PFGW 다음과 같은 입력 파일에이 -f100숫자를 prefactor합니다. 내 컴퓨터 (i5 Haswell)에서 약 2-3 분 내에 PRP (10 ^ (6073-6) -1) / 9 + 6 * 10 ^ 110 또는 {5956} 7 {110}을 찾습니다 . 나는 이전의 모든 제출물보다 조금 더 높은 소매 번호로 6000 자리를 시작 지점으로 선택했습니다.

ABC2 $a-$b & (10^($a-$b)-1)/9+$b*10^$c
a: primes from 6000 to 6200
b: in { 2 4 6 }
c: from 0 to 5990

이 숫자를 얼마나 빨리 찾을 수 있었는지에 따라 자릿수를 쉽게 늘리고 한 시간 내에 PRP를 찾을 수 있습니다. 규칙을 작성하는 방법으로 4 코어에서 실행되는 CPU가 한 시간에 한 번의 PRP 테스트를 완료 하고 PRP를 찾는 데 오랜 시간이 걸리고 내 "검색"만 구성 할 수있는 크기를 찾을 수도 있습니다. 하나의 PRP.

추신 어떤 의미에서, 이것은 입력 파일 이외의 것을 쓰지 않았기 때문에 이것은 "코드"솔루션이 아닙니다 ... 그러나 수학 문제에 대한 많은 한 줄 Mathematica 솔루션은 동일한 방식으로 설명 될 수 있습니다 당신을 위해 열심히 일하는 도서관을 사용합니다. 실제로, 나는 둘 사이에 좋은 선을 그리는 것이 어렵다고 생각합니다. 원하는 경우 PFGW 입력 파일을 작성하고 PFGW를 호출하는 스크립트를 작성할 수 있습니다. 이 스크립트는 4 개의 코어를 모두 사용하고 (내 CPU에서) ~ 4 배까지 검색 속도를 높이기 위해 병렬로 검색 할 수도 있습니다.

PPS LLR 이이 숫자들에 대해 PRP 테스트를 수행 할 수 있다고 생각 하며, PFGW보다 훨씬 빠를 것으로 기대합니다 . 전용 체질 프로그램 (sieving program)은 PFGW의 한 번에 한 번보다 이러한 수치를 고려하는 것이 더 나을 수 있습니다. 이들을 결합하면 현재 솔루션보다 훨씬 더 높은 한계를 뛰어 넘을 수 있다고 확신합니다.


4

Python 2.7, 17-19 자리

11111111171111111

3 초 만에 5111111111111 (13 자리)을 찾았고 3 분 안에 17 자리 최고 소수를 찾았습니다. 대상 머신이이를 실행하여 1 시간 이내에 19 자리의 최고 소수를 얻을 수 있다고 생각합니다. 이 방법은 메모리에서 대상 자릿수의 최대 절반까지 소수를 유지하기 때문에 확장 성이 떨어집니다. 17 자리를 검색하려면 100M 부울 배열을 저장해야합니다. 19 자리에는 1B 요소 배열이 필요하며 23 자리에 도달하기 전에 메모리가 소진됩니다. 아마도 런타임 일 것입니다.

엄청나게 많은 제수의 소수를 포함하지 않는 원시성 테스트 접근법은 훨씬 나아질 것입니다.

#!/usr/bin/env python
import math
import numpy as np
import sys

max_digits = int(sys.argv[1])
max_num = 10**max_digits

print "largest supreme prime of " + str(max_digits) + " or fewer digits"

def sum_product_digits(num):
    add = 0
    mul = 1
    while num:
         add, mul, num = add + num % 10, mul * (num % 10), num / 10
    return add, mul

def primesfrom2to(n):
    # http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Input n>=6, Returns a array of primes, 2 <= p < n """
    sieve = np.ones(n/3 + (n%6==2), dtype=np.bool)
    sieve[0] = False
    for i in xrange(int(n**0.5)/3+1):
        if sieve[i]:
            k=3*i+1|1
            sieve[      ((k*k)/3)      ::2*k] = False
            sieve[(k*k+4*k-2*k*(i&1))/3::2*k] = False
    return np.r_[2,3,((3*np.nonzero(sieve)[0]+1)|1)]

def checkprime(n):
    for divisor in primes:
        if (divisor>math.sqrt(n)):
            break
        if n%divisor==0:
            return False
    return True

# make an array of all primes we need to check as divisors of our max_num
primes = primesfrom2to(math.sqrt(max_num))
# only consider digit counts that are prime
for num_digits in primes:
    if num_digits > max_digits:
        break
    for ones_on_right in range(0,num_digits):
        for mid_prime in ['3','5','7']:
            # assemble a number of the form /1*[357]1*/
            candidate = int('1'*(num_digits-ones_on_right-1)+mid_prime+'1'*ones_on_right)
            # check for primeness of digit sum first digit product first
            add, mul = sum_product_digits(candidate)
            if add in primes and mul in primes:
                # check for primality next
                if checkprime(candidate):
                    # supreme prime!
                    print candidate

3

Mathematica 4211 4259 자리

번호 : {1042} 7 {3168} {388} 3 {3870}

다음 코드에 의해 생성되었습니다.

TimeConstrained[
 Do[
  p = Prime[n];
  curlargest = Catch[
    If[PrimeQ[p + 6],
     list = ConstantArray[1, p];
     Do[
      temp = FromDigits[ReplacePart[list, i -> 7]];
      If[PrimeQ[temp],
       Throw[temp]
       ], {i, p}]
     ];

    If[PrimeQ[p + 4],
     list = ConstantArray[1, p];
     Do[
      temp = FromDigits[ReplacePart[list, i -> 5]];
      If[PrimeQ[temp],
       Throw[temp]
       ], {i, p}]
     ];
    If[PrimeQ[p + 2],
     list = ConstantArray[1, p];
     Do[
      temp = FromDigits[ReplacePart[list, i -> 3]];
      If[PrimeQ[temp],
       Throw[temp]
       ], {i, p}]
     ];
    Throw[curlargest];
    ]

  , {n, 565, 10000}]
 , 60*60]

이 던져는 현재 발견 된 것과 같은 숫자로 다른 숫자에 대한 테스트를 중지합니다. 가장 큰 자릿수에서 테스트를 시작하기 때문에 자릿수가 삼중 항의 구성원이 아닌 한 항상 가장 큰 숫자를 반환합니다.

위의 답변 중 하나의 값 바로 아래에서 테스트를 시작했습니다. :)

완료되면 숫자는 변수 curlargest에 저장됩니다


2

자바 스크립트, 3019 자리, {2,273} 5 {745}

Tom Wu의 BigInteger.js에 포함 된 MillerRabin 테스트를 사용합니다.

한 시간에 0 => 2,046 자리 = {1799} 7 {263} 부터 시작 합니다.

3000 => 3,019 자리 = {2,273} 5 {745} 부터 시작하여 3 초 미만 입니다.

0에서 시작했을 때 프로그램은 건너 뛰었고 마지막으로 발견 된 s-prime 길이의 1.5 배 길이에서 다시 검색을 시작했습니다. 그런 다음 얼마나 빨리 실행되는지 보았을 때 한 시간 안에 3000에서 시작하는 것이 하나 있다고 생각했습니다. 이는 3 초 밖에 걸리지 않았습니다.

http://goo.gl/t3TmTk 여기에서 시도해 볼 수 있습니다
(모든 S- 프라임을 계산하도록 설정하거나 앞으로 건너 뛰십시오).

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

이 프로그램은 모든 "1"의 문자열을 구성하지만 하나의 "3", "5"또는 "7"을 사용하여 작동합니다. "5"로 끝나는 숫자를 거부하기 위해 IsStrPrime 함수에 빠른 검사를 추가했습니다.

if (IsIntPrime(length)) {

    var do3s = IsIntPrime(length + 2);
    var do5s = IsIntPrime(length + 4);
    var do7s = IsIntPrime(length + 6);

    if (do3s || do5s || do7s) {

        // loop through length of number
        var before, digit, after;

        for (var after = 0; after <= length - 1; after++) {

            before = length - after - 1;
            beforeStr = Ones(before);
            afterStr = Ones(after);

            if (do3s && IsStrPrime(beforeStr + (digit = "3") + afterStr)) { RecordAnswer(); if (brk) break; }
            if (AreDone()) break;

            if (do5s && IsStrPrime(beforeStr + (digit = "5") + afterStr)) { RecordAnswer(); if (brk) break; }
            if (AreDone()) break;

            if (do7s && IsStrPrime(beforeStr + (digit = "7") + afterStr)) { RecordAnswer(); if (brk) break; }
            if (AreDone()) break;

            if (after % 10 == 0) document.title = "b=" + bestLength + ", testing=" + length + "-" + after;
        }
    }
}

이것은 꽤 재미 있었다. 몇 년 전에 숫자 제거 소수 자릿수 를 계산하기 위해했던 퍼즐을 상기시킵니다 . 이것은 숫자를 제거해도 나머지 숫자는 여전히 소수 인 소수입니다. 예를 들어 1037은 037, 037, 137, 107 및 103이 소수이므로 숫자가 제거 된 소수입니다. 나는 84 자리의 길이를 발견했으며 내가 아는 가장 긴 길이는 332 자리입니다. 이 퍼즐에 사용 된 기술로 더 오래 찾을 수있을 것입니다. (그러나 시험 번호를 선택하는 것은 조금 까다 롭습니다. 어쩌면?)


RE : 숫자가 소수를 제거 했습니다 . 여기에 있습니다 . 332 자리도 이겼을 것입니다.
primo

0

공리, 3019 자리 숫자 {318} 5 {2700}

)time on

-- Return true if n is pseudo prime else return false
-- **Can Fail**
prime1(n:PI):Boolean==
     n=1=>false
     n<4=>true
     i:=5;sq:=sqrt(1.*n)
     repeat
       if i>sq or i>50000 then break
       if n rem i=0       then return false
       i:=i+2
     if i~=50001        then return true
     --output("i")
     if powmod(3,n,n)=3 then return true
     --output("e")
     false

-- input  'n': must be n>1 prime
-- output [0] if not find any number, else return 
-- [n,a,b,c,z] 'n' digits of solution, 
-- 'a' number of '1', 'b' central digit, 'b' number of final digit '1'
-- 'z' the number found
g(n:PI):List NNI==
    x:=b:=z:=1
    for i in 1..n-1 repeat
        z:=z*10+1
        b:=b*10
    repeat
       --output b
       k:=0    -- 3 5 7 <-> 2 4 6
       for i in [2,4,6] repeat
           ~prime?(n+i)=>0 --somma
           k:=k+1
           t:=z+b*i
           if prime1(t) then return [n,x-1,i+1,n-x,t]
       --if x=1 then output ["k=", k] 
       if k=0  then break
       x:=x+1
       b:=b quo 10
       if b<=0 then break
    [0]

-- start from number of digits n
-- and return g(i) with i prime i>=n 
find(n:PI):List NNI==
    i:=n
    if i rem 2=0 then i:=i+1 
    repeat
        if prime?(i) then --solo le lunghezze prime sono accettate
             output i 
             a:=g(i)
             if a~=[0] then return a
        i:=i+2

529 초 안에 시작 값 3000의 결과

(4) -> find(3000)
   3001
   3011
   3019

   (4)
   [3019, 318, 5, 2700, Omissis]
                                            Type: List NonNegativeInteger
       Time: 0.02 (IN) + 525.50 (EV) + 0.02 (OT) + 3.53 (GC) = 529.07 sec
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.