Uzunluğu, toplamı ve ürünü asal olan en büyük primi bulun


37

Sayı 113, uzunluğu 3asal, dijital toplam 5 = 1 + 1 + 3asal ve dijital ürün asal olan ilk asal sayıdır 3 = 1 * 1 * 3.

Bu 3 özelliğe sahip olan bir prime üstünce asal denir . Asal 11117ve 1111151diğer örneklerdir.

Hedef

Büyük bulabileceği bir program yazın fevkalade asal (örneğin tercih spec olarak iyi bir çağdaş kişisel bilgisayarda bir saatten az olası sayı buraya ).

Bize büyük bir yüce asal vermemelisin. Arama işleminizi gerçekten işe yarayan kodla bize göstermeniz gerekir. Sizin veya başkalarının çözümlerini oluşturabilirsiniz, ancak onlara kredi verdiğinizden emin olun. Bir saat içinde normal bir bilgisayarda gerçekleştirilebilecek en büyük en yüksek üssü bulmaya çalışıyoruz.

puanlama

En büyük üssü bulan makbuz kazanır. Kesin olarak çok sayıda yüksek üssü olduğu ortaya çıkarsa, o zaman en yüksek üssü oluşturan ilk başvuru kazanır.

(Eğer matematiksel olarak kanıtlayabiliyorsanız ya çok sayıda asal sayı olduğunu ya da sınırsız olduğunu ispatlayabilirim çünkü sana sadece 200 ödül temsilcisi vereceğim. :))

ayrıntılar

  • Asallarınızı oluşturmak için herhangi bir kaynağı kullanabilirsiniz (örneğin internet).
  • Olasılıksal temel test yöntemlerini kullanabilirsiniz.
  • Her şey 10 numarada.
  • Sıfır ve bir asal sayılmaz.
  • İçinde bulunduran asal 0bir dijital ürüne sahip olduğu 0açıkça belli değil.
  • Sayfanın daha az karmaşık olması için formda büyük (100+ basamaklı) en büyük harfler kullanın:

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

    Böylece 1111151olarak ifade edilebilir {5}5{1}.


Asalların bir listesiyle başlayabilir miyiz, ya da internetten bir liste alıp saati bir üstünlük kontrolü yaparak geçirebilir miyiz?
Sparr

2
Bilinen en yüksek yüce asalla başlayabilirseniz, bu iki asal arasındaki olası en büyük boşluğu kapsayacak şekilde tam olarak bir saat harcayan bir program yazabilecek olanlar için bir zorluk haline gelir. :(
Sparr

8
0 içermemesinin yanında, olası herhangi bir yüce asalın açıkça 1 ^ n [3 | 5 | 7] 1 ^ m, yani bazı 1'ler, 10'un altındaki herhangi bir asıl ve bazı 1'ler şeklinde olması gerekir. Hemen uygulayabileceğiniz daha fazla kısıtlama var.
Ingo Bürk

3
Ryan, sonsuz sayıda yüksek asalın varlığı ile ilgili olarak MSE ile ilgili bir soru başlattı . Bu soruya dair bir fikriniz varsa, lütfen tartışın!
Semiclassical

1
Şu anda sonsuz sayıda yüksek üssü kanıtlamadığının (ve bunun için önemli miktarda çalışmanın gerçekleştiğinin) kanıt olmadığını kolayca söyleyebilirim. Michaelnielsen.org/polymath1/… 'e göre, primerlerin 246 kadar küçük boşluklarla sınırsız bir şekilde ortaya çıktığını biliyoruz, ancak sonsuz yüce asalların ispatı için, 2, 4 veya 6 boşluk aralığına ihtiyacımız var (prime göre) bir yerde 3, 5 veya 7).
Tim S.

Yanıtlar:


9

Perl, 15101 hane, {83} 7 {15017), 8 dakika. Bulunan en fazla: 72227 basamak

Modülümde kullanma Matematik :: Prime :: Util ve GMP arka ucunda . Bir ES BPSW testiyle (Pari'nin ispseudoprime'sinden biraz daha katı), is_prob_prime () , bir rasgele-temel MR ekleyen is_prime () ve BLS75 T5 veya ECPP'yi çalıştıracak is_provable_prime () dahil olmak üzere bir dizi bileşik testine sahiptir. Bu boyut ve türlerde, bir ispat yapmak uzun zaman alacak. Pedantik verifier altından başka bir MR testine attım. En hızlı bilgisayarım olmayan bir Core2 E7500 ürününde Times (i7-4770K cihazımda 2,5 dakika sürüyor).

Tim S.'nin işaret ettiği gibi, tek bir testin bir saat aldığı noktaya kadar daha büyük değerler aramaya devam edebiliriz. Bu E7500'deki ~ 15000 basamakta, bir MR testi için yaklaşık 26 saniye ve tam is_prime için 2 dakika (deneme bölümü artı base-2 MR artı ES Lucas artı bir rastgele-temel MR). Benim i7-4770K 3 kat daha hızlı. Diğer insanların sonuçlarında nasıl olduğunu görmek için birkaç boyut denedim. ~ 5 dakika sonra her birini öldürerek 8k, 20k ve 16k denedim. Daha sonra her biri ~ 10m olan 15k'lik progresyonda çalıştım ve 4'ünde şanslı oldum.

OpenPFGW'nin PRP testleri 4000 ya da öylesine basamaktan bir kez daha hızlıdır ve 50k + aralığında gerçekten çok daha hızlıdır. Testinde oldukça fazla sayıda yanlış pozitif var, bu da testin harika bir ön test olmasını sağlıyor, ancak yine de sonuçları başka bir şeyle doğrulamak istiyor.

Bu perl dişleriyle veya modüldeki paralel Fibonacci ana bulucu örneklerine benzer MCE kullanılarak paralelleştirilebilir.

Tek çekirdekli kullanarak boşta i7-4770K ile zamanlama ve sonuçlar:

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

32k basamaklı sonuç için, her biri 32000'den başlayan ardışık argümanlarla aynı anda çalışan 6 komut dosyası başlattım. 26.5 dakika sonra biri gösterilen 32063 basamaklı sonuçla sona erdi. 57k için, 57k sonucu 57 dakika içinde geri dönene kadar art arda gelen komut dosyalarının 500'lük giriş artışlarında bir saat boyunca 6 çalışmasına izin verdim. 72k basamaklı sonuç, 70k'lık art arda primerler yaparak bulundu, bu yüzden kesinlikle bir saat içinde bulunmadı (bir kere nereden başlayacağınızı bilseniz bile).

Senaryo:

#!/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";
}

Beni bu kütüphaneyle tanıştırmak için +1! gmpy2Makinemde 10 ^ 7'den küçük primleri yineleme zamanlamaları (CPython ile ve PyPy ile karşılaştırıldığında my_math): codepad.org/aSzc0esT
primo

Beğendiğine sevindim! forprimes { ...do stuff... } 1e7;10x ya da daha hızlı olan başka yollar da var (birçok harika fikir için Pari / GP için övgüler var). Geri bildirimleri her zaman takdir ediyorum, bu nedenle istediğiniz gibi çalışmayan bir şey olursa bana bildirin.
DanaJ

21

PyPy'deki Python 2.7, {2404) 3 {1596) (~ 10 ^ 4000)

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111113111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

4000'den başladıktan yaklaşık 50 dakika sonra bunu buldum. Bu nedenle, bunun bu kod yaklaşımının üst sınırı olduğunu tahmin ediyorum.

Değişim: Bazı uzunlukların, bu tür bir prime üretmede diğerlerinden daha verimli göründüğünü fark ettim, bu nedenle, taşımadan önce, mümkün olan tüm konumlar yerine 1 olmayan 50 rastgele konumu kontrol etmeye karar verdim üzerinde. Bunun performansı artıracağından veya 50'nin doğru olacağından tam olarak emin değilim, ancak göreceğiz.

Ürün gereksiniminin yerine getirilmesi için, sayının asal olanların tümü olması gerektiği gerçeğine dayanarak olasılıklar listesi oluşturulur. Ayrıca, toplam ve uzunluk ilişkisi nedeniyle asal sayı 2 olamaz ve dijital toplam,% 3 gereksinimlerini karşılayarak üçe bölünebilir olmamalıdır.

is_prime http://codepad.org/KtXsydxK tarafından, @primo tarafından yazılmıştır.

Not: Bu is_prime işlevi aslında bir Baillie-PSW psödoprime testidir, ancak bilinen bir karşı örnek yoktur, bu yüzden ayrım hakkında endişelenmeyeceğim.

#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

Maalesef bağlantıdan başka bir şey bilmiyorum. Bağlantıyı burada buldum: codegolf.stackexchange.com/questions/10739/… İlk cevap
isaacg

İyi o zaman. Sana kredi vereceğim.
isaacg

10
Wally olduğu bir ASCII gibi ...
trichoplax

5
Belki de fonksiyonu yeniden adlandırmalısınız is_very_very_very_very_very_very_very_probably_prime()...
trichoplax

2
Mathmatica ve Maple'ın ikisi de aynı yöntemi kullanıyor, bu yüzden o kadar da kötü olamaz.
primo

13

PARI / GP, 4127 basamak

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

Bu oldukça basit bir arama: sadece asal rakam uzunluklarını kontrol edin, daha sonra kullanılacak olası primerleri hesaplayın, sonra tüm olasılıkları tekrarlayın. Kullanılacak 0 veya 1 uygun asal hanenin bulunduğu genel durumları özel olarak sakladım.

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)

Bu oldukça eski bir makinenin bir çekirdeğini hesaplamak için 36 dakika sürdü. Bir saat içinde 5000 rakamın üzerinde böyle bir üssü bulmakta zorluk çekmezdim, eminim ama aynı zamanda sabırsızım.

Daha iyi bir çözüm, en içteki döngüden başka her şeyi yapmak için herhangi bir makul dili kullanmak, daha sonra bu belirli bir hesaplama için optimize edilmiş olan primeform için bir abc dosyası oluşturmak olacaktır . Bu, hesaplamayı en az 10.000 haneye kadar itebilmelidir.

Düzenleme : Yukarıda açıklanan melez çözümü uyguladım, ancak eski makinemde ilk terimi> = 10.000 hane ile bir saatten kısa sürede bulamıyorum. Daha hızlı bir şey üzerinde çalıştırmazsam daha az güçlü bir hedefe geçmek zorunda kalacağım.


4100'den başlamayı nasıl bildin?
isaacg

@isaacg: Sadece 4000'in üzerinde olan (yanlış) Mathematica çözümünden daha büyük olmaya çalışıyordum. 100'ün bir sonraki katına 'hiçbir şey yapmaz' numarası olarak gittim. Aslında bunun talihsiz bir başlangıç ​​yeri olduğu anlaşılıyor, çünkü bir asıl bulmak için beklediğimden daha uzun (ve Mathematica'dan daha uzun!) Gitmek zorunda kaldım.
Charles,

Hayır, aslında inanılmaz derecede şanslıydınız. (4127,3) 4100'den sonraki ilk çift ve bir şans eseri gibi görünüyor. Pek çok çiftin hiç asaliyeti yoktur.
isaacg

@ isaacg: Belki de öyle. Sezgilerim açıkça kapalı, çünkü verilen bir çiftte asal sayı bulma ihtimalinin ~% 80 olmasını beklerdim: 1 - exp (-15 / (4 * log 10)), fakat bundan daha nadir görünüyorlar, yani rastgele {2, 3, 5} gibi hareket etme - boyutlarının düz sayıları (hesaplamayı yapmadığım sürece).
Charles,

@isaacg: Her durumda şu anda bahsettiğim "daha iyi çözüm" üzerinde çalışıyorum: zor işi pfgw'ye zorlamak. 10 ^ 10000'ün üzerindeki ilk 20 çifti hiçbir şey bulamadan aradı ama bu sadece ~ 15 dakika sürdü.
Charles,

7

Mathematica 3181 basamak

Güncelleme: İlk gönderimde bazı ciddi hatalar vardı. Bunun için sonuçları kontrol etmek için biraz zaman ayırmayı başardım. Çıkış, basamakların bir listesi olarak biçimlendirilir. Bu, koşulların her birinin kolayca kontrol edilmesini sağlar.

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

Örnek

Bu benim ilk sınavımdı, 3181 rakamlı bir çözüm arayışı. İlk vakayı 26 saniyede buldu.

Muhakeme geçelim. Sonra programın kendisine gireceğiz.

Başlayalım, yaptığım gibi, "450. Asal nedir?" Bu kadar rakamla bir çözüm bulabilir miyiz (3181)?

primeDigits = Prime[450]

3181


Rakamlara katılarak sayı bulunur.

number = FromDigits[digits];

Ancak, göstermek yerine, rakamların ne olduğunu ve nerede olduklarını sorabiliriz.

DigitCount[number]

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

Bu, 1 rakamının 3180 örneği ve 7 rakamının tek bir örneği olduğu anlamına gelir.

Rakam 7 hangi konumda?

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

142

Yani rakam 7, 142 rakamdır. Diğerleri 1.


Tabii ki, rakamların ürünü 7, asal olmalıdır.

digitProduct = Times @@ digits

7


Ve rakamların toplamı da bir ana.

digitSum = Plus @@ digits
PrimeQ[digitSum]

3187
Doğru


Ve rakamların sayısının asal olduğunu biliyoruz. Unutma, 450. üssü, yani 3118'i seçtik.

Böylece tüm koşullar yerine getirildi.


3
Yanılmıyorsam, toplamı asıl olmayan 4009'dur.
gerw

Bir şey: asal olan tüm basamakların toplamı olmamalı mı? Senin durumunda 4002 * 1 + 7 = 40094003 test etmek zorunda değilsin.
Johnride

2
@ Johnride: Her ikisi de asıl olmalıdır.
gerw

@gerw Doğru. Rakamların sayısı ve rakamların toplamı VE rakamların çarpımı hepsinde asal olmalıdır.
Calvin'in Hobileri

Hepiniz haklıydınız. Daha önceki başvurumda, birincillik için rakam toplamını kontrol etmeyi unuttum. Bu şimdi aşağıdakilerden birinin (hangisi olduğu önemli değil) asal olup olmadığını görerek yapılır: basamak uzunluğu + 2, basamak uzunluğu _4 veya basamak Uzunluk +6.
DavidC

7

Python 2.7, 6217 basamak: {23} 5 {6193) 6 dakika 51 saniye

Kendi sürümüm üzerinde çalışıyordum ve @issacg'ın beni çok benzer bir yaklaşımla yumrukladığını, is_ (very_probably) _prime () ile de olsa hayal kırıklığına uğrattım. Bununla birlikte, daha az zamanda daha iyi bir cevapla sonuçlanan bazı önemli farklılıklara sahip olduğumu görüyorum (aynı zamanda is_prime kullandığımda). Ayrıca 4000 den başlatırken bu açıklığa kavuşturmak için, ben sadece 26 dakika içinde daha iyi bir 4001 haneli cevap ({393} 7 {3607}) varmak kullanarak 37 saniye standart (ayrıca sürümü 2.7 de) Python yorumlayıcısı, değil PyPy sürümü. Ayrıca, sayıları kontrol ederken 'spot' değilim. Tüm adaylar kontrol edilir.

İşte temel iyileştirmeler:

  1. Ve ("küçük asal" sürümlerini kontrol etmek için) asal bir liste oluşturmak için bir asal üreteç kullanın ( https://stackoverflow.com/questions/567222/simple-prime-generator-in-python/568618#568618 ) ve uygun sayıda uzunluk üretmek için.

  2. Zamanımızı, en küçük olanı değil, en uzun olan en büyük sayıyı bulmak için harcıyoruz, bu yüzden ilk kontrol için mümkün olan en küçük sayıları değil, en küçük olanını yapıyorum. Sonra, bir kişi bulunduğunda, hemen bir sonraki uzunluğa geçebiliriz.

EDIT: Şimdi çok işlemeli

Bu önceki sürümlerde önemli bir değişikliktir. Daha önce, 8 çekirdekli makinemin çok çalıştığını fark etmedim, bu yüzden Python'da (ilk kez) çoklu işlemede elimi denemeye karar verdim. Sonuçlar çok güzel!

Bu versiyonda, 7 çocuk süreci ortaya çıkar ve bu da potansiyel olasılıklar kuyruğundan bir 'görev' alır (num_length + uygun rakamlar). Birisini bulana kadar farklı [7,5,3] pozisyonları deneyerek çalkalanırlar. Varsa, bulunan en uzun uzunluğun ana işlemini bildirir. Çocuklar daha kısa olan bir num_length üzerinde çalışıyorlarsa, sadece kurtarırlar ve bir sonraki uzunluğu elde ederler.

Bu koşuya 6000 ile başladım ve hala çalışıyor, fakat şu ana kadar sonuçlardan çok memnunum.

Program henüz doğru bir şekilde durmuyor, fakat benim için çok büyük bir şey değil.

Şimdi kod:

#!/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 bağlantısını [kırılmış, gerekirse] içe aktarma olarak temsil ederseniz daha temiz okuyacaktır
Sparr

Bence kafa karıştırıcı olurdu, çünkü diğer ucundaki kod böyle bir şeyden etkilenmez.
mkoistinen

isaacg'nin sözdizimini kullanın. URL'yi yorumlayın, sonra varolmayan bir paketten içe aktarın (onun durumunda my_math)
Sparr

1
Aslında sayıları en büyüğünden en küçüğüne de yapıyorum. Kod farklılıklarımızın çok önemli olduğunu sanmıyorum. Aradaki farkın bilgisayarlarımızda kodumuzdan daha fazla yatmasını bekliyorum. Yine de, aferin ve siteye hoş geldiniz.
isaacg

my_mathla, bir primas listesi oluşturmak için de kullanılabilir while prime < 20006: prime = next_prime(prime). En az 3 kat daha hızlı gen_primesve daha verimli bellek gibi görünüyor .
primo

6

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

İlham ve hileler için sizler ve hepiniz için teşekkür ederim.
Ayrıca ustaca soru soran @ Calvin'in bu soru için Hobileri.

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

Hesaplama gücünüzü bağışlamak veya performansı merak etmek istiyorsanız, kodu kopyalayıp derleyin. ;) Yüklenmiş GMP'ye ihtiyacınız olacak.

#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 basamak, {5956} 7 {110}

PFGW'yi aşağıdaki giriş dosyasıyla birlikte çalıştırın -f100ve sayıları önceden belirlemek için. Bilgisayarımda yaklaşık 2-3 CPU dakikada (i5 Haswell), PRP (10 ^ (6073-6) -1) / 9 + 6 * 10 ^ 110 veya {5956} 7 {110} 'ı bulur . Daha önceki gönderilerden biraz daha yüksek olan, hiçbir şey-up-my-up-up numarası olarak başlangıç ​​noktası olarak 6000 rakam seçtim.

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

Bunu ne kadar çabuk bulabildiğime bağlı olarak, rakam sayısını kolayca arttırabilir ve bir saat içinde hala bir PRP bulabilirim. Kuralların nasıl yazılacağıyla, 4 çekirdekte çalışan CPU'mun bir saatte bir PRP testini tamamlayabildiği, bir PRP bulmak için uzun zaman harcadığı ve "arama" ımı yalnızca oluşturduğu boyutu bile bulabilirim bir PRP’nin

Not: Bazı açılardan, bu bir "kod" çözümü değildir, çünkü girdi dosyasından başka bir şey yazmamıştım ... ama sonra, matematik problemlerine yönelik tek satırlı Mathematica çözümleri aynı şekilde tanımlanabilirdi. sizin için zor olan bir kütüphane kullanmak. Gerçekte, ikisi arasında iyi bir çizgi çizmek zor olduğunu düşünüyorum. İsterseniz, PFGW giriş dosyasını oluşturan ve PFGW'yi çağıran bir komut dosyası yazabilirim. Komut, 4 çekirdeğin tümünü kullanmak ve aramayı ~ 4 kat hızlandırmak için bile (CPU'umda) paralel olarak arama yapabilir.

PPS bence LLR Bu numaralar için PRP testleri yapabilir ve bunu olmasını beklediğiniz kadar hızlı PFGW daha . Özel bir eleme programı, bu sayıları çarpanlara ayırmada PFGW'nin tek seferde olduğundan daha iyi olabilir. Bunları birleştirdiyseniz, sınırları mevcut çözümlerden çok daha yüksek tutabileceğinizden eminim.


4

Python 2.7, 17-19 basamak

11111111171111111

3 saniyede 5111111111111 (13 hane) ve bu 17 hane yüksek asal 3 dakikada bulundu. Hedef makinenin bunu çalıştırabileceğini ve bir saatten daha kısa bir sürede 19 basamaklı bir üstün üssü alabileceğini tahmin edeceğim. Bu yaklaşım iyi ölçeklenemez çünkü asılları bellekteki hedef hane sayısının yarısına kadar tutar. 17 basamaklı arama 100M boolean dizisini kaydetmeyi gerektirir. 19 hane 1B eleman dizisi ister ve 23 hane gelmeden önce hafıza boşalırdı. Çalışma zamanı muhtemelen de olurdu.

Gülünç derecede büyük bir bölen primer dizisi içermeyen primallik testi yaklaşımları çok daha iyi sonuç verecektir.

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

Numara ile: {3168} {1042} 7 {388} 3 {3870}

Aşağıdaki kod tarafından üretildi:

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]

Atmalar, şu anda bulunan rakamlarla aynı rakamlara sahip diğer numaralar için testi durdurmasına neden olur. En önemli basamakta test etmeye başladığından, bu, basamak sayısı bir asal üçlünün üyesi olmadığı sürece her zaman en büyük sayıyı döndüreceği anlamına gelir.

Basitçe önceki cevaplardan birinin değerinin hemen altında test etmeye başladı :)

İşlem tamamlandığında, sayı değişken değişkende saklanır


2

JavaScript, 3019 basamak, {2,273} 5 {745}

Bu, Tom Wu tarafından BigInteger.js'de bulunan MillerRabin testini kullanıyor.

0'dan başlayarak => 2,046 hane = {1799} 7 {263} bir saatte .

3000'den başlayarak => 3,019 hane = {2,273} 5 {745} bir saatte, 3 saniyeden az .

0'dan başladığında, program öne atladı ve en son 1.5X uzunluğunda 1.5X uzunluğunda tekrar aramaya başladı. Sonra ne kadar hızlı çalıştığını gördüğümde, bir saatte 3000'den başlayan bir tane bulacağını tahmin etmiştim;

Burada deneyebilirsiniz: http://goo.gl/t3TmTk
(Tüm s-primeleri hesaplamak için ayarlayın veya ileri atlayın.)

görüntü tanımını buraya girin görüntü tanımını buraya girin
görüntü tanımını buraya girin

Program, tüm "1" lerden ancak bir "3", "5" veya "7" dizeleri oluşturarak çalışır. "5" ile biten sayıları reddetmek için IsStrPrime işlevine hızlı bir denetim ekledim.

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

Bu oldukça eğlenceliydi. Bana, bir rakamı kaldırılmış asal sayı denilen şeyi hesaplamak için yıllar önce yaptığım bir bulmacayı hatırlatıyor . Bu, herhangi bir rakamı kaldırırsanız kalan sayının hala asal olduğu bir asal sayıdır. Örneğin, 1037, bir basamağa kaldırılmış bir asaldır, çünkü 1037, 037, 137, 107 ve 103 asaldır. 84 hane uzunluğunda bir tane buldum ve bildiğim en uzun 332 hane uzunluğunda. Eminim bu yapboz için kullanılan tekniklerle daha uzun süre bulabiliriz. (Ancak deneme numaralarını seçmek biraz daha zordur - belki?)


RE: rakam kaldırıldı asal, biz burada bir tane var . 332 hane de kazanacaktı.
primo

0

Aksiyom, 3019 basamak {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

3000 başlangıç ​​değerinden 529 sn'de sonuç

(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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.