Temukan prime terbesar yang panjang, jumlah dan produknya prima

37

Jumlahnya 113adalah prima pertama yang panjangnya 3prima, jumlah digital 5 = 1 + 1 + 3prima, dan produk digital 3 = 1 * 1 * 3prima.

Prime yang memiliki 3 properti ini akan disebut prime prime . Bilangan prima 11117dan 1111151contoh lainnya.

Tujuan

Tulis sebuah program yang dapat menemukan bilangan prima terbesar yang sangat mungkin dalam waktu kurang dari satu jam di komputer pribadi modern yang layak (seperti spesifikasi pilihan di sini ).

Anda seharusnya tidak hanya memberi kami prima tertinggi yang besar. Anda harus menunjukkan kepada kami proses pencarian Anda dengan kode yang benar-benar berfungsi. Anda dapat membangun di atas solusi Anda atau orang lain tetapi pastikan untuk memberi mereka pujian. Kami agak secara komunikatif berusaha menemukan prime tertinggi tertinggi yang dapat direalisasikan pada komputer normal dalam satu jam.

Mencetak gol

Pengajuan yang menemukan pemenang tertinggi tertinggi menang. Jika ternyata ada banyak bilangan prima tertinggi maka pengajuan pertama yang menghasilkan kemenangan tertinggi tertinggi.

(Jika Anda dapat membuktikan secara matematis bahwa ada banyak prima tertinggi atau tidak terhingga, saya akan memberi Anda 200 perwakilan bayaran hanya karena. :))

Detail

  • Anda dapat menggunakan sumber apa pun untuk menghasilkan bilangan prima Anda (mis. Internet).
  • Anda dapat menggunakan metode pengujian prima probabilistik.
  • Semuanya ada di base 10.
  • Nol dan satu TIDAK dianggap prima.
  • Primes yang mengandung 0memiliki produk digital 0sehingga jelas mereka tidak bisa menjadi yang tertinggi.
  • Untuk menjaga agar halaman tidak berantakan, beri bilangan prima tertinggi (100+ digit) dalam bentuk:

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

    Jadi 1111151bisa dinyatakan sebagai {5}5{1}.

Hobi Calvin
sumber
Bisakah kita mulai dengan daftar bilangan prima, atau mengambil daftar dari internet, dan menghabiskan waktu melakukan cek supremeness?
Sparr
2
Jika Anda bisa mulai dengan prima tertinggi tertinggi yang diketahui maka ini menjadi tantangan bagi siapa yang dapat menulis sebuah program yang menghabiskan waktu tepat satu jam yang mencakup celah terbesar yang mungkin ada antara dua bilangan prima tertinggi. :(
Sparr
8
Di samping tidak mengandung 0, setiap prime prime potensial harus jelas dari bentuk 1 ^ n [3 | 5 | 7] 1 ^ m, yaitu beberapa 1s, setiap prime di bawah 10 dan beberapa 1s lainnya. Ada lebih banyak kendala yang bisa Anda atasi saat itu juga.
Ingo Bürk
3
Ryan telah memulai pertanyaan terkait MSE tentang keberadaan bilangan prima tertinggi yang tak terhingga banyaknya. Jika Anda memiliki wawasan untuk pertanyaan itu, silakan mempertimbangkan!
Semiklasik
1
Saya dapat dengan mudah menunjukkan bahwa saat ini tidak ada bukti jumlah prima tertinggi yang tak terbatas (dan bahwa sejumlah besar pekerjaan telah dilakukan untuk itu). Menurut michaelnielsen.org/polymath1/… , kita tahu bahwa bilangan prima datang tanpa batas dengan celah sekecil 246, tetapi untuk bukti bilangan prima tertinggi yang tak terbatas, kita memerlukan celah 2, 4, atau 6 (sesuai dengan bilangan prima dengan a 3, 5, atau 7 di suatu tempat di dalamnya).
Tim S.

Jawaban:

9

Perl, 15101 digit, {83} 7 {15017}, 8 menit. Maks ditemukan: 72227 digit

Menggunakan modul saya Math :: Prime :: Util dan bagian belakang GMP -nya . Ini memiliki sejumlah tes komposit termasuk is_prob_prime () dengan tes ES BPSW (sedikit lebih ketat daripada ispseudoprime Pari), is_prime () yang menambahkan satu MR berbasis acak, dan is_provable_prime () yang akan menjalankan BLS75 T5 atau ECPP. Pada ukuran dan tipe ini, melakukan pembuktian akan memakan waktu lama. Saya melemparkan tes MR lain di sub verifikasi pedantic. Kali pada Core2 E7500 yang jelas bukan komputer tercepat saya (dibutuhkan 2,5 menit pada i7-4770K saya).

Seperti yang ditunjukkan Tim S., kami dapat terus mencari nilai yang lebih besar, sampai pada titik di mana tes tunggal memakan waktu satu jam. Pada ~ 15000 digit pada E7500 ini, dibutuhkan sekitar 26 detik untuk tes MR dan 2 menit untuk is_prime penuh (divisi percobaan ditambah MR basis-2 ditambah ES Lucas plus satu MR basis acak). I7-4770K saya lebih cepat 3x. Saya mencoba beberapa ukuran, terutama melihat bagaimana hasilnya pada hasil orang lain. Saya mencoba 8k, 20k, dan 16k, membunuh masing-masing setelah ~ 5 menit. Saya kemudian mencoba 15k dalam progres untuk ~ 10m masing-masing dan beruntung pada yang keempat.

Tes PRP OpenPFGW tentu saja lebih cepat setelah melewati 4000 atau lebih digit, dan memang jauh lebih cepat dalam kisaran 50k +. Namun, tes ini memiliki jumlah positif palsu yang cukup banyak, yang menjadikannya sebagai pra-tes yang bagus tetapi seseorang masih ingin memverifikasi hasilnya dengan sesuatu yang lain.

Ini bisa diparalelkan dengan benang perl atau menggunakan MCE yang mirip dengan contoh pencari perdana Fibonacci paralel dalam modul.

Pengaturan waktu dan hasil pada i7-4770K idle menggunakan inti tunggal:

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

Untuk hasil 32k digit, saya memulai 6 skrip yang berjalan pada waktu yang sama, masing-masing dengan argumen berurutan mulai dari 32000. Setelah 26,5 menit satu selesai dengan hasil 3203 digit yang ditunjukkan. Untuk 57k saya membiarkan skrip berturut-turut menjalankan 6 sekaligus selama satu jam dalam penambahan input 500 hingga hasil 57k kembali dalam 57 menit. Hasil digit 72k ditemukan dengan melakukan bilangan prima berturut-turut dari 70k ke atas, jadi pasti tidak ditemukan dalam satu jam (meskipun begitu Anda tahu harus mulai dari mana, itu).

Naskah:

#!/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";
}
DanaJ
sumber
+1 untuk memperkenalkan saya ke perpustakaan ini! Pengaturan waktu pada mesin saya untuk mengulangi bilangan prima kurang dari 10 ^ 7 (dibandingkan dengan CPython dengan gmpy2, dan PyPy dengan my_math): codepad.org/aSzc0esT
primo
Senang kamu menyukainya! Ada cara lain termasuk forprimes { ...do stuff... } 1e7;yang 10x atau lebih cepat (pujian ke Pari / GP untuk banyak ide hebat). Saya selalu menghargai umpan balik, jadi beri tahu saya jika ada sesuatu yang tidak berjalan sesuai keinginan Anda.
DanaJ
21

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

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111113111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

Menemukan ini sekitar 50 menit setelah mulai dari 4000. Oleh karena itu, saya akan memperkirakan ini adalah batas atas dari pendekatan kode ini.

Ubah: Saya perhatikan bahwa beberapa panjang tampaknya lebih bermanfaat untuk menghasilkan prime semacam ini daripada yang lain, jadi saya memutuskan untuk hanya memeriksa 50 lokasi acak digit yang bukan 1 bukannya semua lokasi yang mungkin, sebelum pindah di. Saya tidak sepenuhnya yakin ini akan meningkatkan kinerja, atau 50 benar, tetapi kita akan lihat.

Daftar kemungkinan dihasilkan berdasarkan fakta bahwa untuk persyaratan produk yang harus dipenuhi, nomor harus semua yang kecuali prima. Selain itu, prime tidak boleh 2 karena hubungan jumlah dan panjang, dan jumlah digital tidak boleh dibagi tiga, memberikan persyaratan% 3.

is_prime diambil dari http://codepad.org/KtXsydxK , yang ditulis oleh @primo

Catatan: fungsi is_prime ini sebenarnya adalah tes pseudoprime Baillie-PSW, tetapi tidak ada contoh tandingan yang diketahui, jadi saya tidak akan khawatir tentang perbedaannya.

#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
isaacg
sumber
Sayangnya, saya tahu tidak lebih dari tautannya. Saya menemukan tautan di sini: codegolf.stackexchange.com/questions/10739/... Jawaban pertama
isaacg
Baiklah kalau begitu. Saya akan menghargai Anda.
isaacg
10
Ini seperti ASCII tempat
pesta
5
Mungkin Anda harus mengganti nama fungsinya is_very_very_very_very_very_very_very_probably_prime()...
trichoplax
2
Mathmatica dan Maple keduanya menggunakan metode yang sama, jadi tidak mungkin seburuk itu.
Primo
13

PARI / GP, 4127 digit

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

Ini adalah pencarian yang cukup mudah: periksa hanya panjang digit prima, lalu hitung bilangan prima yang mungkin digunakan, lalu ulangi semua kemungkinan. Saya khusus menggunakan kasus-kasus umum di mana ada 0 atau 1 digit prima yang cocok untuk digunakan.

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)

Ini membutuhkan waktu 36 menit untuk menghitung pada satu inti dari mesin yang cukup lama. Saya tidak akan kesulitan menemukan yang terbaik lebih dari 5000 digit dalam satu jam, saya yakin, tapi saya juga tidak sabar.

Solusi yang lebih baik adalah dengan menggunakan bahasa apa pun yang masuk akal untuk melakukan segalanya kecuali loop yang paling dalam, lalu buat file abc untuk primeform yang dioptimalkan untuk jenis perhitungan tertentu. Ini harus dapat mendorong perhitungan hingga setidaknya 10.000 digit.

Sunting : Saya menerapkan solusi hibrida yang dijelaskan di atas, tetapi pada mesin lama saya, saya tidak dapat menemukan istilah pertama dengan> = 10.000 digit dalam waktu kurang dari satu jam. Kecuali saya menjalankannya pada sesuatu yang lebih cepat saya harus mengubah ke target yang kurang tinggi.

Charles
sumber
Bagaimana Anda tahu mulai dari 4100?
isaacg
@isaacg: Saya hanya mencoba untuk menjadi lebih besar dari solusi Mathematica (salah), yang hanya lebih dari 4000. Saya hanya pergi ke kelipatan 100 berikutnya sebagai nomor 'no-up-my-sleeve'. Sebenarnya sepertinya ini adalah tempat awal yang tidak menguntungkan, karena saya harus pergi lebih lama dari yang saya harapkan (dan lebih lama dari Mathematica!) Untuk menemukan yang terbaik.
Charles
Tidak, sebenarnya, kamu sangat beruntung. (4127,3) adalah pasangan pertama setelah 4100, dan kebetulan itu kebetulan memiliki prima. Banyak pasangan tidak memiliki prime sama sekali.
isaacg
@isaacg: Mungkin begitu. Heuristik saya jelas mati, karena saya akan mengharapkan probabilitas ~ 80% untuk menemukan yang terbaik dalam pasangan yang diberikan: 1 - exp (-15 / (4 * log 10)), tetapi mereka tampaknya lebih jarang daripada itu, sehingga mereka jangan bertingkah seperti acak {2, 3, 5} -jumlah angka yang kecil (kecuali saya melakukan kesalahan perhitungan).
Charles
@isaacg: Bagaimanapun saya sedang mengerjakan "solusi yang lebih baik" yang saya sebutkan sekarang: mendorong kerja keras ke pfgw. Itu mencari 20 pasangan pertama di atas 10 ^ 10.000 tanpa menemukan apa pun tetapi hanya butuh ~ 15 menit.
Charles
7

Mathematica 3181 digit

Pembaruan: Ada beberapa kesalahan serius dalam pengiriman pertama saya. Saya dapat meluangkan waktu untuk memeriksa hasilnya untuk yang satu ini. Output diformat sebagai daftar digit. Itu membuat mudah memeriksa masing-masing kondisi.

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

Contoh

Ini adalah tes pertama saya, pencarian solusi dengan 3181 digit. Ditemukan kasus pertama dalam 26 detik.

Mari kita bahas alasannya. Kemudian kita akan masuk ke program itu sendiri.

Mari kita mulai, seperti yang saya lakukan, "Apa prime 450?" Bisakah kita menemukan solusi dengan angka sebanyak itu (3181)?

primeDigits = Prime[450]

3181


Nomornya ditemukan dengan bergabung dengan angka.

number = FromDigits[digits];

Tapi alih-alih menampilkannya, kita bisa bertanya apa digit dan di mana mereka berada.

DigitCount[number]

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

Ini berarti ada 3180 contoh digit 1, dan satu instance digit 7.

Di posisi apa angka 7?

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

142

Jadi digit 7 adalah digit ke 142. Yang lainnya adalah 1.


Tentu saja, produk digit harus prima, yaitu 7.

digitProduct = Times @@ digits

7


Dan jumlah digit juga prima.

digitSum = Plus @@ digits
PrimeQ[digitSum]

3187
Benar


Dan kita tahu bahwa jumlah digit adalah yang utama. Ingat, kami memilih perdana ke-450, yaitu 3118.

Jadi semua syarat sudah terpenuhi.

DavidC
sumber
3
Jika saya tidak salah, jumlahnya adalah 4009 yang tidak prima.
gerw
Satu hal: bukankah itu harus menjadi jumlah dari semua digit yang prima dan bukan jumlah digit? Dalam kasus Anda, Anda harus menguji 4002 * 1 + 7 = 4009dan bukan 4003 sesuai dengan spesifikasi.
Johnride
2
@ Johnride: Keduanya harus prima.
gerw
@gerw benar. Jumlah digit DAN jumlah digit DAN produk digit semuanya harus prima.
Hobi Calvin
Anda semua benar. Dalam pengajuan saya sebelumnya saya lupa memeriksa jumlah digit untuk primality. Ini sekarang dilakukan dengan melihat apakah salah satu dari berikut ini (tidak masalah yang mana) adalah prima: panjang digit + 2, panjang digit _4, atau Panjang digit +6.
DavidC
7

Python 2.7, 6217 digit: {23} 5 {6193} 6 mnt 51 dtk

Saya sedang mengerjakan versi saya sendiri dan kecewa melihat @issacg telah mengalahkan saya dengan pukulan dengan pendekatan yang sangat mirip, walaupun dengan is_ (very_probably) _prime (). Namun, saya melihat bahwa saya memiliki beberapa perbedaan signifikan yang menghasilkan jawaban yang lebih baik dalam waktu yang lebih singkat (ketika saya juga menggunakan is_prime). Untuk memperjelas ini, ketika juga mulai dari 4000, saya sampai pada jawaban 4001 digit yang lebih baik ({393} 7 {3607}) hanya dalam 26 menit, 37 detik menggunakan juru bahasa Python standar (juga pada versi 2.7), bukan PyPy versi. Juga, saya tidak 'melihat' memeriksa nomor. Semua kandidat diperiksa.

Inilah peningkatan utama:

  1. Gunakan generator prima ( https://stackoverflow.com/questions/567222/simple-prime-generator-in-python/568618#568618 ) untuk membuat daftar bilangan prima yang akan diperiksa dan (versinya "primes kecil") dan untuk menghasilkan panjang nomor yang memenuhi syarat.

  2. Kami ingin menghabiskan waktu mencari prime prima terbesar dari panjang yang diberikan, bukan yang terkecil, jadi, saya membangun angka terbesar yang mungkin pertama untuk memeriksa, bukan yang terkecil. Kemudian, begitu satu ditemukan, kita dapat langsung beralih ke panjang berikutnya.

EDIT: Sekarang dengan multiprocessing

Ini adalah perubahan signifikan ke versi sebelumnya. Sebelumnya, saya perhatikan bahwa mesin 8-core saya hampir tidak berfungsi, jadi, saya memutuskan untuk mencoba tangan saya di multiprocessing dengan Python (pertama kali). Hasilnya sangat bagus!

Dalam versi ini, 7 proses anak-anak melahirkan, yang mengambil 'tugas' dari antrian kemungkinan potensial (num_length + digit yang memenuhi syarat). Mereka bergerak melalui mencoba berbagai posisi [7,5,3] hingga menemukan satu. Jika ya, informasikan proses master dari panjang terpanjang baru yang telah ditemukan. Jika anak-anak mengerjakan num_length yang lebih pendek, mereka hanya menebus, dan mendapatkan panjang berikutnya.

Saya mulai menjalankan ini dengan 6000, dan masih berjalan, tapi sejauh ini, saya sangat senang dengan hasilnya.

Program ini belum berhenti dengan benar, tetapi bukan masalah besar bagi saya.

Sekarang kodenya:

#!/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))
mkoistinen
sumber
itu akan terbaca dengan lebih bersih jika Anda mewakili tautan codepad sebagai impor [rusak, jika perlu]
Sparr
Saya pikir itu akan membingungkan, karena kode di ujung tidak benar-benar dapat diimpor seperti itu.
mkoistinen
gunakan sintaks isaacg. komentar URL, lalu impor dari paket yang tidak ada (my_math, dalam kasusnya)
Sparr
1
Sebenarnya, saya menghasilkan angka dari yang terbesar hingga yang terkecil juga. Saya tidak berpikir perbedaan kode kami sangat signifikan. Saya berharap perbedaannya terletak lebih pada komputer kita daripada kode kita. Meskipun demikian, dilakukan dengan baik, dan selamat datang di situs.
isaacg
my_mathjuga dapat digunakan untuk menghasilkan daftar bilangan prima, à la while prime < 20006: prime = next_prime(prime). Tampaknya sekitar 3 kali lebih cepat gen_primes, dan jauh lebih efisien memori.
Primo
6

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

Kudos to @issacg dan kalian semua untuk inspirasi dan triknya.
Dan juga penanya ulung @ Calvin Hobbies untuk pertanyaan ini.

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

Jika Anda merasa ingin menyumbangkan kekuatan komputasi Anda atau ingin tahu kinerja, silakan menyalin kode dan kompilasi. ;) Anda perlu GMP diinstal.

#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;
}
Vektor
sumber
5

PFGW, 6067 digit, {5956} 7 {110}

Jalankan PFGW dengan file input berikut dan -f100untuk menentukan angka-angka. Dalam sekitar 2-3 menit CPU di komputer saya (i5 Haswell), ia menemukan PRP (10 ^ (6073-6) -1) / 9 + 6 * 10 ^ 110, atau {5956} 7 {110} . Saya memilih 6000 digit sebagai titik awal sebagai nomor tanpa lengan saya yang sedikit lebih tinggi dari semua pengiriman sebelumnya.

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

Berdasarkan seberapa cepat saya dapat menemukan yang satu ini, saya dapat dengan mudah menambah jumlah digit dan masih menemukan PRP dalam satu jam. Dengan bagaimana aturan ditulis, saya bahkan mungkin menemukan ukuran di mana CPU saya, berjalan pada semua 4 core, dapat menyelesaikan satu tes PRP dalam satu jam, membutuhkan waktu lama untuk menemukan PRP, dan meminta "pencarian" saya hanya terdiri dari satu PRP.

PS Dalam beberapa hal, ini bukan solusi "kode" karena saya tidak menulis apa pun selain file input ... tapi kemudian, banyak solusi satu-baris Mathematica untuk masalah matematika dapat dijelaskan dengan cara yang sama, seperti yang bisa menggunakan perpustakaan yang melakukan kerja keras untuk Anda. Pada kenyataannya, saya pikir sulit untuk menarik garis yang bagus di antara keduanya. Jika Anda suka, saya bisa menulis skrip yang membuat file input PFGW dan memanggil PFGW. Script bahkan dapat mencari secara paralel, untuk menggunakan semua 4 core dan mempercepat pencarian dengan ~ 4 kali (pada CPU saya).

PPS Saya pikir LLR dapat melakukan tes PRP untuk angka-angka ini, dan saya berharap itu jauh lebih cepat daripada PFGW . Program pengayakan khusus juga bisa lebih baik dalam memfaktorkan angka-angka ini daripada PFGW satu per satu. Jika Anda menggabungkan ini, saya yakin Anda bisa mendorong batas lebih tinggi dari solusi saat ini.

Tim S.
sumber
4

Python 2.7, 17-19 digit

11111111171111111

Ditemukan 511111111111111 (13 digit) dalam 3 detik dan 17 digit prime tertinggi ini dalam 3 menit. Saya kira mesin target bisa menjalankan ini dan mendapatkan 19 digit prime tertinggi dalam waktu kurang dari satu jam. Pendekatan ini tidak skala dengan baik karena membuat bilangan prima hingga setengah dari jumlah digit target dalam memori. Pencarian 17 digit membutuhkan penyimpanan array 100 juta boolean. 19 digit membutuhkan array elemen 1B, dan memori akan habis sebelum mencapai 23 digit. Runtime mungkin juga demikian.

Pendekatan uji primality yang tidak melibatkan sejumlah besar pembagi bilangan prima akan jauh lebih baik.

#!/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
Sparr
sumber
3

Mathematica 4211 4259 digit

Dengan nomor: {1042} 7 {3168} {388} 3 {3870}

Yang dihasilkan oleh kode berikut:

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]

Lemparan tersebut menyebabkannya berhenti menguji untuk nomor lain dengan angka yang sama dengan yang saat ini ditemukan. karena ia mulai menguji pada digit paling signifikan, ini berarti bahwa ia selalu mengembalikan angka terbesar kecuali jika jumlah digit adalah anggota dari triplet utama.

Cukup mulai menguji tepat di bawah nilai salah satu jawaban sebelumnya :)

Setelah selesai, nomor tersebut disimpan dalam variabel curlargest

Menghitung
sumber
2

JavaScript, 3019 digit, {2.273} 5 {745}

Ini menggunakan tes MillerRabin yang disertakan dalam BigInteger.js oleh Tom Wu.

Mulai dari 0 => 2.046 digit = {1799} 7 {263} dalam satu jam .

Mulai dari 3000 => 3.019 digit = {2.273} 5 {745} dalam satu jam, kurang dari 3 detik .

Ketika dimulai dari 0, program melompati dan mulai mencari lagi pada panjang 1,5X panjang s-prime terakhir yang ditemukan. Kemudian ketika saya melihat seberapa cepat itu berjalan saya kira itu akan menemukan satu mulai dari 3000 dalam satu jam - yang dilakukan hanya dengan 3 detik.

Anda dapat mencobanya di sini: http://goo.gl/t3TmTk
(Setel untuk menghitung semua s-primes, atau lewati.)

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini
masukkan deskripsi gambar di sini

Program ini bekerja dengan membangun string semua "1", tetapi dengan satu "3", "5", atau "7". Saya menambahkan cek cepat pada fungsi IsStrPrime untuk menolak angka yang diakhiri dengan "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;
        }
    }
}

Ini sangat menyenangkan. Mengingatkan saya pada sebuah teka-teki yang saya lakukan bertahun-tahun yang lalu untuk menghitung apa yang disebut prima digit dihapus . Ini adalah bilangan prima yang jika Anda menghapus angka apa pun, maka bilangan yang tersisa masih prima. Misalnya 1037 adalah digit prima yang dihapus karena 1037, 037, 137, 107, dan 103 adalah prima. Saya menemukan satu 84 angka, dan yang terlama saya ketahui adalah 332 digit. Saya yakin kita bisa menemukan yang lebih lama dengan teknik yang digunakan untuk teka-teki ini. (Tetapi memilih nomor uji coba sedikit lebih rumit - mungkin?)

JeffSB
sumber
RE: digit dihapus prima, kami sudah punya itu di sini . 332 angka akan menang juga.
primo
0

Aksioma, 3019 digit {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

hasil dari nilai awal 3000 dalam 529 detik

(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
RosLuP
sumber