Tìm số nguyên tố lớn nhất có độ dài, tổng và sản phẩm là số nguyên tố


37

Số 113là số nguyên tố đầu tiên có độ dài 3là số nguyên tố, tổng số 5 = 1 + 1 + 3là số nguyên tố và sản phẩm kỹ thuật số 3 = 1 * 1 * 3là số nguyên tố.

Một nguyên tố có 3 thuộc tính này sẽ được gọi là cực kỳ nguyên tố . Các số nguyên tố 111171111151là ví dụ khác.

Mục tiêu

Viết một chương trình có thể tìm thấy số nguyên tố cực lớn nhất có thể trong chưa đầy một giờ trên một máy tính cá nhân hiện đại đàng hoàng (chẳng hạn như thông số kỹ thuật ưa thích ở đây ).

Bạn không nên đơn giản cung cấp cho chúng tôi một thủ tướng tối cao lớn. Bạn cần cho chúng tôi thấy quá trình tìm kiếm của bạn với mã thực sự hoạt động. Bạn có thể xây dựng dựa trên các giải pháp của bạn hoặc của người khác nhưng hãy chắc chắn cung cấp cho họ tín dụng. Chúng tôi đang cố gắng tìm kiếm số nguyên tố tối cao lớn nhất có thể thực hiện được trên một máy tính bình thường trong một giờ.

Chấm điểm

Trình đệ trình tìm thấy thủ tướng tối cao lớn nhất sẽ thắng. Nếu nó chỉ ra rằng có rất nhiều số nguyên tố tối cao thì đệ trình đầu tiên tạo ra chiến thắng tối cao cao nhất.

(Nếu bạn có thể chứng minh một cách toán học rằng có hoặc không có vô số số nguyên tố tối cao tôi sẽ cung cấp cho bạn 200 tiền thưởng chỉ vì. :))

Chi tiết

  • Bạn có thể sử dụng bất kỳ nguồn nào để tạo số nguyên tố của mình (ví dụ: internet).
  • Bạn có thể sử dụng các phương pháp thử nghiệm xác suất chính.
  • Tất cả mọi thứ là trong cơ sở 10.
  • Không và một KHÔNG được coi là nguyên tố.
  • Các số nguyên tố 0có một sản phẩm kỹ thuật số 0rõ ràng là chúng không thể là tối cao.
  • Để giữ cho trang ít lộn xộn hơn, hãy đặt các số nguyên tố tối cao (hơn 100 chữ số) ở dạng:

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

    Vì vậy, 1111151có thể được thể hiện như {5}5{1}.


Chúng ta có thể bắt đầu với một danh sách các số nguyên tố, hoặc lấy một danh sách từ internet và dành hàng giờ để kiểm tra độ tối cao không?
Sparr

2
Nếu bạn có thể bắt đầu với số nguyên tố tối cao được biết đến cao nhất thì điều này trở thành một thách thức cho người có thể viết một chương trình dành chính xác một giờ kéo dài khoảng cách lớn nhất có thể giữa hai số nguyên tố tối cao. :(
Sparr

8
Bên cạnh không chứa 0, bất kỳ số nguyên tố tối cao tiềm năng nào rõ ràng phải có dạng 1 ^ n [3 | 5 | 7] 1 ^ m, tức là một số 1, bất kỳ số nguyên tố nào dưới 10 và một số 1 khác. Có nhiều ràng buộc hơn bạn có thể đặt nó ngay lập tức.
Ingo Bürk

3
Ryan đã bắt đầu một câu hỏi liên quan trên MSE về sự tồn tại của vô số các số nguyên tố tối cao. Nếu bạn có bất kỳ hiểu biết nào cho câu hỏi đó, xin vui lòng cân nhắc!
Bán nguyệt

1
Tôi có thể dễ dàng chỉ ra rằng hiện tại không có bằng chứng về một số lượng vô hạn các số nguyên tố tối cao (và một số lượng đáng kể công việc đã đi về phía nó). Theo michaelnielsen.org/polymath1/ , chúng ta biết rằng các số nguyên tố xuất hiện vô hạn với các khoảng trống nhỏ như 246, nhưng để chứng minh các số nguyên tố tối cao vô hạn, chúng ta cần một khoảng cách 2, 4 hoặc 6 (tương ứng với các số nguyên tố với 3, 5 hoặc 7 ở đâu đó trong chúng).
Tim S.

Câu trả lời:


9

Perl, 15101 chữ số, {83} 7 {15017}, 8 phút. Tìm thấy tối đa: 72227 chữ số

Sử dụng mô-đun Math :: Prime :: Util và phần cuối của nó . Nó có một số thử nghiệm tính tổng hợp bao gồm is_prob_prime () với thử nghiệm ES BPSW (nghiêm ngặt hơn một chút so với ispseudoprime của Pari), is_prime () sẽ thêm một MR cơ sở ngẫu nhiên và is_provable_prime () sẽ chạy BLS75 Ở các kích cỡ và loại này, làm một bằng chứng sẽ mất nhiều thời gian. Tôi đã ném trong một thử nghiệm MR khác trong phụ xác minh pedantic. Thời gian trên Core2 E7500, đây chắc chắn không phải là máy tính nhanh nhất của tôi (mất 2,5 phút trên i7-4770K của tôi).

Như Tim S. chỉ ra, chúng tôi có thể tiếp tục tìm kiếm các giá trị lớn hơn, cho đến khi một thử nghiệm duy nhất mất một giờ. Với ~ 15000 chữ số trên E7500 này, mất khoảng 26 giây cho thử nghiệm MR và 2 phút cho toàn bộ is_prime (phân chia thử nghiệm cộng với MR 2 cơ sở cộng với ES Lucas cộng với một MR cơ sở ngẫu nhiên). I7-4770K của tôi nhanh hơn gấp 3 lần. Tôi đã thử một vài kích cỡ, chủ yếu là xem nó đã làm như thế nào trên kết quả của người khác. Tôi đã thử 8k, 20k và 16k, mỗi lần giết sau 5 phút. Sau đó tôi đã thử 15k trong tiến trình cho ~ 10m mỗi lần và gặp may mắn ở lần thứ 4.

Các bài kiểm tra PRP của OpenPFGW chắc chắn nhanh hơn một lần khi vượt qua 4000 chữ số hoặc hơn, và thực sự nhanh hơn nhiều trong phạm vi 50k +. Tuy nhiên, bài kiểm tra của nó có số lượng dương tính giả khá cao, điều này làm cho nó trở thành một bài kiểm tra trước tuyệt vời nhưng người ta vẫn muốn xác minh kết quả bằng một thứ khác.

Điều này có thể được song song với các luồng perl hoặc sử dụng MCE tương tự như các ví dụ về trình tìm số nguyên tố Fibonacci song song trong mô-đun.

Thời gian và kết quả trên i7-4770K nhàn rỗi bằng cách sử dụng lõi đơn:

  • nhập 3000, 16 giây, 3019 chữ số, {318} 5 {2700}
  • nhập 4000, 47 giây, 4001 chữ số, {393} 7 {3607}
  • nhập 4100, 5 giây, 4127 chữ số, {29} 7 {4097}
  • nhập 6217, 5 giây, 6217 chữ số, {23} 5 {6193}
  • nhập 6500, 5 phút, 6547 chữ số, {598} 5 {5948}
  • nhập 7000, 15 phút, 7013 chữ số, {2411} 7 {4601}
  • nhập 9000, 11 phút, 9001 chữ số, {952} 7 {8048}
  • nhập 12000, 10 phút, 12007 chữ số, {652} 5 {11354}
  • nhập 15100, 2,5 phút, 15101 chữ số, {83} 7 {15017}
  • nhập 24600, 47 phút, 24671 chữ số, {621} 7 {24049}
  • nhập 32060, 18 phút, 32063 chữ số, {83} 7 {31979}
  • nhập 57000, 39 phút, 57037 chữ số, {112} 5 {56924}
  • nhập 72225, 42 phút, 72227 chữ số, {16} 3 {72210}

Đối với kết quả 32 chữ số, tôi bắt đầu 6 tập lệnh chạy cùng lúc với mỗi tập lệnh liên tiếp bắt đầu từ 32000. Sau 26,5 phút, một tập kết thúc với kết quả 32063 chữ số được hiển thị. Với giá 57k, tôi để các tập lệnh liên tiếp chạy 6 lần trong một giờ với mức tăng đầu vào là 500 cho đến khi kết quả 57k được trả về sau 57 phút. Kết quả 72 chữ số đã được tìm thấy bằng cách thực hiện các số nguyên tố liên tiếp từ 70 nghìn trở lên, do đó chắc chắn không tìm thấy trong một giờ (mặc dù một khi bạn biết bắt đầu từ đâu, thì đó là).

Kịch bản:

#!/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 để giới thiệu tôi với thư viện này! Thời gian trên máy của tôi để lặp lại các số nguyên tố nhỏ hơn 10 ^ 7 (so với CPython với gmpy2và PyPy với my_math): codepad.org/aSzc0esT
primo

Vui vì bạn thích nó! Có nhiều cách khác bao gồm cách forprimes { ...do stuff... } 1e7;nhanh hơn gấp 10 lần (chuyển sang Pari / GP cho nhiều ý tưởng tuyệt vời). Tôi luôn đánh giá cao phản hồi vì vậy hãy cho tôi biết nếu có gì đó không hoạt động theo cách bạn muốn.
DanaJ

21

Python 2.7 trên PyPy, {2404} 3 {1596} (~ 10 ^ 4000)

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111113111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

Tìm thấy cái này khoảng 50 phút sau khi bắt đầu từ 4000. Do đó, tôi sẽ ước tính đây là giới hạn trên của phương pháp mã này.

Thay đổi: Tôi đã nhận thấy rằng một số độ dài dường như hiệu quả hơn khi tạo loại nguyên tố này so với các số nguyên tố khác, vì vậy tôi đã quyết định chỉ kiểm tra 50 vị trí ngẫu nhiên của chữ số không phải là 1 thay vì tất cả các vị trí có thể, trước khi di chuyển trên. Tôi không hoàn toàn chắc chắn rằng điều này sẽ cải thiện hiệu suất hoặc 50 là chính xác, nhưng chúng ta sẽ thấy.

Danh sách khả năng được tạo ra dựa trên thực tế là để đáp ứng yêu cầu sản phẩm, số lượng phải là tất cả ngoại trừ một số nguyên tố. Ngoài ra, số nguyên tố không thể là 2 do mối quan hệ tổng và độ dài và tổng số không được chia hết cho ba, đưa ra yêu cầu% 3.

is_prime được lấy từ http://codepad.org/KtXsydxK , được viết bởi @primo

Lưu ý: hàm is_prime này thực sự là một thử nghiệm giả ngẫu nhiên Baillie-PSW, nhưng không có ví dụ phản biện nào được biết đến, vì vậy tôi sẽ không lo lắng về sự khác biệt.

#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

Tôi không biết gì hơn là liên kết, thật không may. Tôi tìm thấy liên kết ở đây: codegolf.stackexchange.com/questions/10739/ Câu trả lời đầu tiên
isaacg

Vâng, sau đó. Tôi sẽ ghi có cho bạn.
isaacg

10
Nó giống như một ASCII đâu Wally ...
Trichoplax adhaerens

5
Có lẽ bạn nên đổi tên chức năng is_very_very_very_very_very_very_very_probably_prime()...
trichoplax

2
MathmaticaMaple đều sử dụng cùng một phương pháp, vì vậy nó không thể tệ đến thế.
primo

13

PARI / GP, 4127 chữ số

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

Đây là một tìm kiếm khá đơn giản: chỉ kiểm tra độ dài chữ số nguyên tố, sau đó tính các số nguyên tố có thể sử dụng, sau đó lặp qua tất cả các khả năng. Tôi đặc biệt áp dụng các trường hợp phổ biến trong đó có 0 hoặc 1 chữ số nguyên tố phù hợp để sử dụng.

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)

Điều này mất 36 phút để tính toán trên một lõi của một máy khá cũ. Tôi sẽ không gặp khó khăn gì khi tìm số nguyên tố như vậy hơn 5000 chữ số trong một giờ, tôi chắc chắn, nhưng tôi cũng không kiên nhẫn.

Một giải pháp tốt hơn là sử dụng bất kỳ ngôn ngữ hợp lý nào để thực hiện mọi thứ trừ vòng lặp trong cùng, sau đó xây dựng tệp abc cho primeform được tối ưu hóa cho loại tính toán cụ thể đó. Điều này sẽ có thể đẩy tính toán lên đến ít nhất 10.000 chữ số.

Chỉnh sửa : Tôi đã triển khai giải pháp kết hợp được mô tả ở trên, nhưng trên máy cũ của tôi, tôi không thể tìm thấy thuật ngữ đầu tiên với> = 10.000 chữ số trong vòng chưa đầy một giờ. Trừ khi tôi chạy nó trên một cái gì đó nhanh hơn, tôi sẽ phải đổi sang một mục tiêu ít cao hơn.


Làm thế nào bạn biết để bắt đầu từ 4100?
isaacg

@isaacg: Tôi chỉ cố gắng lớn hơn giải pháp Mathicala (không chính xác), chỉ hơn 4000. Tôi chỉ đi đến bội số tiếp theo của 100 với tư cách là số 'không có gì thay đổi'. Trên thực tế có vẻ như đây là một nơi khởi đầu không may, vì tôi phải đi lâu hơn tôi mong đợi (và lâu hơn Mathicala!) Để tìm một vị tướng.
Charles

Không, thực sự, bạn đã vô cùng may mắn. (4127,3) là cặp đầu tiên sau 4100 và hoàn toàn có thể có một số nguyên tố. Rất nhiều cặp không có số nguyên tố nào cả.
isaacg

@isaacg: Có lẽ vậy. Các heuristic của tôi rõ ràng đã tắt, vì tôi đã dự đoán xác suất ~ 80% để tìm một số nguyên tố trong một cặp nhất định: 1 - exp (-15 / (4 * log 10)), nhưng chúng dường như hiếm hơn thế, vì vậy chúng không hành động như các số ngẫu nhiên {2, 3, 5} có kích thước của chúng (trừ khi tôi thực hiện phép tính).
Charles

@isaacg: Trong mọi trường hợp tôi đang làm việc với "giải pháp tốt hơn" mà tôi đã đề cập bây giờ: đẩy công việc khó khăn lên pfgw. Nó đã tìm kiếm 20 cặp đầu tiên trên 10 ^ 10000 mà không tìm thấy gì nhưng chỉ mất ~ 15 phút.
Charles

7

Toán học 3181 chữ số

Cập nhật: Có một số sai lầm nghiêm trọng trong lần gửi đầu tiên của tôi. Tôi đã có thể dành một chút thời gian để kiểm tra kết quả cho việc này. Đầu ra được định dạng như một danh sách các chữ số. Điều đó làm cho dễ dàng kiểm tra từng điều kiện.

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]]

Thí dụ

Đây là thử nghiệm đầu tiên của tôi, tìm kiếm một giải pháp với 3181 chữ số. Nó tìm thấy trường hợp đầu tiên trong 26 giây.

Chúng ta hãy đi qua lý luận. Sau đó, chúng tôi sẽ bước vào chương trình chính nó.

Hãy bắt đầu, như tôi đã làm, "Thủ tướng thứ 450 là gì?" Chúng ta có thể tìm một giải pháp có nhiều chữ số đó không (3181)?

primeDigits = Prime[450]

3181


Số được tìm thấy bằng cách tham gia các chữ số.

number = FromDigits[digits];

Nhưng thay vì hiển thị nó, chúng ta có thể hỏi thay vào đó các chữ số là gì và chúng nằm ở đâu.

DigitCount[number]

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

Điều này có nghĩa là có 3180 trường hợp của chữ số 1 và một trường hợp duy nhất của chữ số 7.

Ở vị trí nào là chữ số 7?

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

142

Vậy chữ số 7 là chữ số thứ 142. Tất cả những cái khác là 1.


Tất nhiên, tích của các chữ số phải là số nguyên tố, cụ thể là 7.

digitProduct = Times @@ digits

7


Và tổng các chữ số cũng là một số nguyên tố.

digitSum = Plus @@ digits
PrimeQ[digitSum]

3187
Đúng


Và chúng ta biết rằng số chữ số là một số nguyên tố. Hãy nhớ rằng, chúng tôi đã chọn số nguyên tố thứ 450, cụ thể là 3118.

Vì vậy, tất cả các điều kiện đã được đáp ứng.


3
Nếu tôi không nhầm, tổng của nó là 4009 không phải là số nguyên tố.
gerw

Một điều: không nên là tổng của tất cả các chữ số là số nguyên tố chứ không phải số chữ số? Trong trường hợp của bạn, bạn sẽ phải kiểm tra 4002 * 1 + 7 = 4009và không phải 4003 theo thông số kỹ thuật.
Johnride

2
@ John: Cả hai nên là số nguyên tố.
gerw

@gerw Đúng rồi. Số chữ số VÀ tổng các chữ số VÀ tích của các chữ số đều phải là số nguyên tố.
Sở thích của Calvin

Tất cả các bạn đã đúng. Trong lần gửi trước, tôi đã quên kiểm tra tổng số cho tính nguyên thủy. Điều này bây giờ được thực hiện bằng cách xem liệu một trong những điều sau đây (không thành vấn đề) là số nguyên tố: chiều dài chữ số + 2, chiều dài chữ số _4 hoặc Độ dài chữ số +6.
DavidC

7

Python 2.7, 6217 chữ số: {23} 5 {6193} 6 phút 51 giây

Tôi đã làm việc trên phiên bản của riêng mình và thất vọng khi thấy rằng @issacg đã đánh tôi bằng cú đấm với cách tiếp cận rất giống nhau, mặc dù với is_ (rất_probossible) _prime (). Tuy nhiên, tôi thấy rằng tôi có một số khác biệt đáng kể dẫn đến câu trả lời tốt hơn trong thời gian ngắn hơn (khi tôi cũng sử dụng is_prime). Để làm rõ điều này, khi cũng bắt đầu từ 4000, tôi đi đến câu trả lời 4001 chữ số tốt hơn ({393} 7 {3607}) chỉ trong 26 phút, 37 giây bằng trình thông dịch Python chuẩn (cũng ở phiên bản 2.7), chứ không phải PyPy phiên bản. Ngoài ra, tôi không 'tại chỗ' kiểm tra các con số. Tất cả các ứng cử viên được kiểm tra.

Đây là những cải tiến chính:

  1. Sử dụng trình tạo số nguyên tố ( https://stackoverflow.com/questions/567222/simple-prime-generator-in-python/568618#568618 ) để tạo danh sách các số nguyên tố để kiểm tra và (phiên bản "số nguyên tố nhỏ" của anh ta) và để tạo độ dài số đủ điều kiện.

  2. Chúng tôi muốn dành thời gian tìm kiếm số nguyên tố tối cao lớn nhất có độ dài nhất định, không phải nhỏ nhất, vì vậy, tôi xây dựng các số lớn nhất có thể trước để kiểm tra, không phải nhỏ nhất. Sau đó, một khi được tìm thấy, chúng ta có thể ngay lập tức chuyển sang độ dài tiếp theo.

EDIT: Bây giờ với đa xử lý

Đây là một thay đổi đáng kể cho các phiên bản trước. Trước đây, tôi nhận thấy rằng máy 8 lõi của tôi hầu như không hoạt động, vì vậy, tôi đã quyết định thử sử dụng đa xử lý trong Python (lần đầu tiên). Kết quả rất tốt đẹp!

Trong phiên bản này, 7 quy trình con được sinh ra, lấy 'nhiệm vụ' ra khỏi hàng đợi các khả năng tiềm năng (num_length + chữ số đủ điều kiện). Họ lướt qua thử các vị trí [7,5,3] khác nhau cho đến khi tìm thấy một vị trí. Nếu có, thông báo cho quá trình tổng thể về độ dài mới nhất đã được tìm thấy. Nếu trẻ em đang làm việc trên một num_length ngắn hơn, chúng chỉ bảo lãnh và đi lấy chiều dài tiếp theo.

Tôi đã bắt đầu chạy này với 6000 và nó vẫn đang chạy, nhưng cho đến nay, tôi rất hài lòng với kết quả.

Chương trình chưa dừng lại chính xác, nhưng không phải là một vấn đề lớn với tôi.

Bây giờ mã:

#!/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))

nó sẽ đọc rõ hơn nếu bạn biểu thị liên kết bảng mã dưới dạng nhập [bị hỏng, nếu cần]
Sparr

Tôi nghĩ điều đó sẽ gây nhầm lẫn, vì mã ở đầu kia không thực sự có thể nhập được như thế.
mkoistinen

sử dụng cú pháp của isaacg. nhận xét URL, sau đó nhập từ gói không tồn tại (my_math, trong trường hợp của anh ấy)
Sparr

1
Trên thực tế, tôi cũng tạo ra các số từ lớn nhất đến nhỏ nhất. Tôi không nghĩ rằng sự khác biệt mã của chúng tôi là rất đáng kể. Tôi mong đợi sự khác biệt sẽ nằm nhiều hơn trong máy tính của chúng tôi so với mã của chúng tôi. Tuy nhiên, cũng được thực hiện, và chào mừng đến với trang web.
isaacg

my_mathcũng có thể được sử dụng để tạo ra một danh sách các số nguyên tố, à la while prime < 20006: prime = next_prime(prime). Có vẻ là nhanh gấp khoảng 3 lầngen_primes và hiệu quả bộ nhớ cao hơn nhiều.
Primo

6

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

Kudos đến @issacg và tất cả các bạn cho những cảm hứng và thủ thuật.
Và cũng là người hỏi câu hỏi thành thạo @ Sở thích của Calvin cho câu hỏi này.

Biên dịch: gcc -I/usr/local/include -o p_out p.c -pthread -L/usr/local/lib -lgmp

Nếu bạn cảm thấy muốn tặng sức mạnh tính toán hoặc tò mò về hiệu suất, hãy sao chép mã và biên dịch. ;) Bạn sẽ cần cài đặt 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 chữ số, {5956} 7 {110}

Chạy PFGW với tệp đầu vào sau và -f100để sắp xếp trước các số. Trong khoảng 2-3 phút CPU trên máy tính của tôi (i5 Haswell), nó tìm thấy PRP (10 ^ (6073-6) -1) / 9 + 6 * 10 ^ 110 hoặc {5956} 7 {110} . Tôi đã chọn 6000 chữ số làm điểm bắt đầu làm số không có gì thay đổi so với tất cả các lần gửi trước đó.

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

Dựa trên mức độ nhanh chóng tôi có thể tìm thấy cái này, tôi có thể dễ dàng tăng số lượng chữ số và vẫn tìm thấy PRP trong vòng một giờ. Với cách viết các quy tắc, tôi thậm chí có thể tìm thấy kích thước mà CPU của tôi, chạy trên cả 4 lõi, có thể hoàn thành một bài kiểm tra PRP trong một giờ, mất một nhiều thời gian để tìm PRP và chỉ có "tìm kiếm" của tôi của một PRP.

PS Trong một số ý nghĩa, đây không phải là một giải pháp "mã" bởi vì tôi đã không viết bất cứ điều gì ngoài tệp đầu vào ... nhưng sau đó, nhiều giải pháp Mathicala một dòng cho các vấn đề toán học có thể được mô tả theo cách tương tự, như có thể sử dụng một thư viện làm công việc khó khăn cho bạn. Trong thực tế, tôi nghĩ thật khó để vạch ra một ranh giới tốt giữa hai người. Nếu bạn thích, tôi có thể viết một tập lệnh tạo tệp đầu vào PFGW và gọi PFGW. Kịch bản thậm chí có thể tìm kiếm song song, để sử dụng tất cả 4 lõi và tăng tốc độ tìm kiếm lên ~ 4 lần (trên CPU của tôi).

PPS Tôi nghĩ LLR có thể thực hiện các bài kiểm tra PRP cho những con số này và tôi hy vọng nó sẽ nhanh hơn nhiều so với PFGW . Một chương trình sàng chuyên dụng cũng có thể tốt hơn trong việc bao thanh toán những con số này so với một lần tại PFGW. Nếu bạn kết hợp những thứ này, tôi chắc chắn rằng bạn có thể đẩy giới hạn cao hơn nhiều so với các giải pháp hiện tại.


4

Python 2.7, 17-19 chữ số

11111111171111111

Tìm thấy 5111111111111 (13 chữ số) trong 3 giây và số nguyên tố tối cao 17 chữ số này trong 3 phút. Tôi đoán rằng cỗ máy mục tiêu có thể chạy cái này và có được số nguyên tố tối cao 19 chữ số trong vòng chưa đầy một giờ. Cách tiếp cận này không mở rộng tốt vì nó giữ số nguyên tố lên tới một nửa số chữ số đích trong bộ nhớ. Tìm kiếm 17 chữ số yêu cầu lưu trữ một mảng gồm 100 triệu booleans. 19 chữ số sẽ yêu cầu mảng phần tử 1B và bộ nhớ sẽ cạn kiệt trước khi nhận được 23 chữ số. Thời gian chạy có lẽ cũng vậy.

Các phương pháp kiểm tra tính nguyên thủy không liên quan đến một số lượng lớn các số nguyên tố chia sẽ có giá tốt hơn nhiều.

#!/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

Toán học 4211 4259 chữ số

Với số: {1042} 7 {3168} {388} 3 {3870}

Được tạo bởi đoạn mã sau:

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]

Các cú ném khiến nó dừng kiểm tra các số khác có cùng chữ số với số hiện được tìm thấy. vì nó bắt đầu thử nghiệm ở chữ số có nghĩa nhất, điều này có nghĩa là nó luôn trả về số lớn nhất trừ khi số chữ số là thành viên của bộ ba số nguyên tố.

Đơn giản chỉ cần bắt đầu thử nghiệm ngay dưới giá trị của một trong những câu trả lời trước :)

Khi nó kết thúc, số được lưu trữ trong biến số lớn nhất


2

JavaScript, 3019 chữ số, {2,273} 5 {745}

Điều này sử dụng thử nghiệm MillerRabin có trong BigInteger.js của Tom Wu.

Bắt đầu từ 0 => 2.046 chữ số = {1799} 7 {263} trong một giờ .

Bắt đầu từ 3000 => 3,019 chữ số = {2,273} 5 {745} trong một giờ, chưa đầy 3 giây .

Khi nó bắt đầu từ 0, chương trình đã bỏ qua và bắt đầu tìm kiếm lại với độ dài 1,5 lần chiều dài của s-Prime cuối cùng được tìm thấy. Sau đó, khi tôi thấy nó chạy nhanh như thế nào, tôi đoán nó sẽ tìm thấy một cái bắt đầu từ 3000 trong một giờ - điều mà nó đã làm chỉ với 3 giây rảnh rỗi.

Bạn có thể dùng thử tại đây: http://goo.gl/t3TmTk
(Đặt để tính tất cả các số nguyên tố hoặc bỏ qua phía trước.)

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây
nhập mô tả hình ảnh ở đây

Chương trình hoạt động bằng cách xây dựng các chuỗi của tất cả "1", nhưng với một "3", "5" hoặc "7". Tôi đã thêm một kiểm tra nhanh trong hàm IsStrPrime để từ chối các số kết thúc bằng "5".

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;
        }
    }
}

Điều này khá thú vị. Nhắc nhở tôi về một câu đố tôi đã làm từ nhiều năm trước để tính toán cái được gọi là số nguyên tố bị loại bỏ . Đây là số nguyên tố mà nếu bạn loại bỏ bất kỳ chữ số nào, thì số còn lại vẫn là số nguyên tố. Ví dụ 1037 là một số nguyên tố bị loại bỏ bởi vì 1037, 037, 137, 107 và 103 là số nguyên tố. Tôi tìm thấy một chữ số dài 84 chữ số và đoạn dài nhất tôi biết là dài 332 chữ số. Tôi chắc rằng chúng ta có thể tìm thấy lâu hơn nữa với các kỹ thuật được sử dụng cho câu đố này. (Nhưng việc chọn số dùng thử sẽ khó hơn một chút - có thể?)


RE: chữ số đã bị xóa, chúng ta đã có cái đó ở đây . 332 chữ số cũng sẽ giành chiến thắng.
primo

0

Tiên đề, 3019 chữ số {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

kết quả từ giá trị bắt đầu 3000 trong 529 giây

(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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.