長さ、和、積が素数である最大の素数を見つける


37

数値113は、長さ3が素数、デジタル合計5 = 1 + 1 + 3が素数、デジタル積3 = 1 * 1 * 3が素数である最初の素数です。

これら3つの特性を持つ素数は、最高素数と呼ばれます。プライム111171111151は他の例です。

ゴール

まともな最新のパーソナルコンピューター(ここで推奨される仕様など)で1時間以内に可能な限り最大の素数を見つけることができるプログラムを作成します。

単に最高の素数を与えてはいけません。実際に動作するコードで検索プロセスを示す必要があります。自分や他の人のソリューションを基に構築できますが、必ずクレジットを与えるようにしてください。私たちは、通常のコンピューターで1時間で実現可能な最大の素数を見つけようと共同で試みています。

得点

最大のプライムプライムを見つけたサブミッションが勝ちます。有限数の最高素数があることが判明した場合、最高最高素数を生成する最初のサブミッションが勝ちます。

(数え切れないほど多くの最高素数があるかどうかを数学的に証明できる場合は、200の報奨金を提供します。理由は:))

詳細

  • 任意のソースを使用して素数を生成できます(インターネットなど)。
  • 確率的素数検定法を使用できます。
  • すべてがベース10にあります。
  • 0と1は素数とは見なされません。
  • を含むプライムには0デジタル製品がある0ため、最高になれないことは明らかです。
  • ページを整理するために、フォームに大きな(100桁以上の)最高プライムを配置します。

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

    だから、1111151のように表現することができ{5}5{1}


プライムのリストから始めたり、インターネットからリストを取得して、1時間かけて最高度のチェックを行うことはできますか?
スパー14

2
最高の既知の最高素数から始めることができる場合、これは、2つの最高素数間の可能な限り大きなギャップにまたがる正確に1時間を費やすプログラムを誰が作成できるかという課題になります。:(
Sparr 14

8
0を含まないことに加えて、潜在的な最高素数は明らかに1 ^ n [3 | 5 | 7] 1 ^ mの形式でなければなりません。すぐに追加できる制約は他にもあります。
インゴバーク14

3
ライアンは、無限に多くの最高素数の存在に関して、MSEに関連した質問を始めました。その質問についての洞察をお持ちの場合は、ご検討ください。
半古典的14

1
現在、無限の数の最高素数の証拠がないことを簡単に示すことができます(そして、かなりの量の仕事がそれに向かっています)。michaelnielsen.org/polymath1/…によると、素数は246程度の小さなギャップを伴って無限に続くことを知っていますが、無限の最高素数の証明には、2、4、または6の素数が必要です(以下の素数に対応)それらのどこかに3、5、または7)。
ティムS. 14

回答:


9

Perl、15101桁、{83} 7 {15017}、8分。見つかった最大値:72227桁

私のモジュールMath :: Prime :: UtilとそのGMPバックエンドを使用します。ES BPSWテストを伴うis_prob_prime()(Pariのispseudoprimeよりわずかに厳しい)、is_prime()は1つのランダムベースMRを追加し、is_provable_prime()はBLS75 T5またはECPPを実行します。これらのサイズとタイプでは、証明を行うのに時間がかかります。私は、徹底的な検証サブで別のMRテストを投げました。間違いなく私の最速のコンピューターではないCore2 E7500での時間(i7-4770Kでは2.5分かかります)。

Tim S.が指摘するように、1回のテストに1時間かかるまで、より大きな値を検索し続けることができました。このE7500の約15000桁では、MRテストに約26秒、is_prime全体(試行区分+ベース2 MR + ESルーカス+ 1つのランダムベースMR)に2分かかります。私のi7-4770Kは3倍以上高速です。主に他の人の結果にどのように影響するかを見て、いくつかのサイズを試しました。8k、20k、および16kを試し、それぞれ5分後に殺しました。その後、それぞれ約10メートルで15kのプログレッションを試し、4日目にラッキーになりました。

OpenPFGWのPRPテストは、4000桁を超えると確かに高速になり、実際には50k +の範囲ではるかに高速になります。ただし、そのテストにはかなりの数の誤検出があり、これは素晴らしい事前テストになりますが、結果を他の何かで検証したいと思っています。

これは、perlスレッドで並列化するか、モジュールの並列フィボナッチプライムファインダーの例と同様のMCEを使用して並列化できます。

シングルコアを使用したアイドル状態のi7-4770Kでのタイミングと結果:

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

32k桁の結果の場合、6つのスクリプトを同時に実行し、それぞれ32000から始まる連続した引数を使用して実行しました。26.5分後、32063桁の結果で終了しました。57kの場合、57分で57kの結果が返されるまで、500の入力増分で1時間に6回連続してスクリプトを実行します。72k桁の結果は、70kから連続した素数を実行することで発見されたため、1時間では絶対に見つかりません(ただし、どこから始めればよいかはわかりますが)。

スクリプト:

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

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

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

このライブラリを紹介してくれた+1 私のマシンで10 ^ 7未満の素数を反復するタイミング(とCPython gmpy2、およびとPyPyと比較my_math):codepad.org/aSzc0esT
primo

気に入ってくれてうれしい!forprimes { ...do stuff... } 1e7;10倍以上の高速化を含む他の方法もあります(多くの優れたアイデアをPari / GPに提供します)。私はいつもフィードバックに感謝していますので、あなたが望むように何かがうまくいかない場合はお知らせください。
DanaJ

21

PyPy上のPython 2.7、{2404} 3 {1596}(〜10 ^ 4000)

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111113111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

4000から開始してから約50分後にこれを見つけました。したがって、これがこのコードアプローチの上限であると推定します。

変更:この種の素数を生成するのに、他の長さよりも実りのある長さがあることに気づいたので、移動する前に、可能な場所の代わりに1ではない数字のランダムな場所を50個だけチェックすることにしましたに。これによりパフォーマンスが向上するか、50が正しいかは完全にはわかりませんが、後で確認します。

可能性リストは、製品の要件が満たされるために、プライムを除くすべてのものでなければならないという事実に基づいて生成されます。さらに、合計と長さの関係のために素数を2にすることはできません。また、デジタル合計は3で割り切れてはならず、%3の要件があります。

@primo によって作成されたhttp://codepad.org/KtXsydxKから取得したis_prime

注:このis_prime関数は実際にはBaillie-PSW疑似プライムテストですが、既知の反例はないため、区別について心配する必要はありません。

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

残念ながら、私はリンクについてしか知りません。ここでリンクを見つけました:codegolf.stackexchange.com/questions/10739/…最初の答え
isaacg 14

じゃあ。クレジットを差し上げます。
isaacg 14

10
それは...ウォーリーだASCIIのようなものだ
センモウヒラムシ

5
たぶん、あなたは機能の名前を変更する必要がありますis_very_very_very_very_very_very_very_probably_prime()...
センモウヒラムシ

2
MathmaticaMapleはどちらも同じメソッドを使用するため、それほど悪くはありません。
primo

13

PARI / GP、4127桁

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

これはかなり簡単な検索です。素数の長さのみをチェックし、使用可能な素数を計算してから、すべての可能性を繰り返します。使用する適切な素数が0または1個ある一般的なケースを特別にケースしました。

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)

これは、かなり古いマシンの1つのコアで計算するのに36分かかりました。1時間で5000桁以上のこのような素数を見つけるのに問題はないでしょう、私は確信していますが、私はまた焦ります。

より良い解決策は、合理的な言語を使用して最も内側のループ以外のすべてを実行し、その特定の種類の計算に最適化されたprimeformの abcファイルを構築することです。これにより、計算を少なくとも10,000桁までプッシュできるはずです。

編集:上記のハイブリッドソリューションを実装しましたが、古いマシンでは、1時間以内に10,000桁以上の最初の用語が見つかりません。より高速なもので実行しない限り、より高いターゲットに変更する必要があります。


4100で始めることをどのように知りましたか?
isaacg 14

@isaacg:私はちょうど(誤った)Mathematicaソリューション(4000を少し上回る)よりも大きくしようとしていました。「ノースリーブアップ」の数として100の倍数になりました。実際、素数を見つけるには予想よりも長く(そしてMathematicaよりも長く)行かなければならなかったので、これは不幸な出発点だったようです。
チャールズ14

いいえ、実際、あなたは非常に幸運でした。(4127,3)は4100の後の最初のペアであり、偶然にも素数を持つことがあります。多くのペアにはプライムがまったくありません。
isaacg 14

@isaacg:たぶんそう。与えられたペアの素数を見つける確率が〜80%になると予想されるため、私のヒューリスティックは明らかにオフになっています:1-exp(-15 /(4 * log 10))、しかしそれらはそれよりも少ないようですランダムな{2、3、5}のような滑らかな数字のように振る舞わないでください(計算を間違えない限り)。
チャールズ14

@isaacg:いずれにせよ、私が今述べた「より良い解決策」に取り組んでいます:努力をpfgwにプッシュします。何も検出せずに10 ^ 10000を超える最初の20ペアを検索しましたが、15分しかかかりませんでした。
チャールズ14

7

Mathematica 3181桁

更新:最初の提出でいくつかの重大な間違いがありました。この結果を確認することに時間を割くことができました。出力は、数字のリストとしてフォーマットされます。これにより、各条件を簡単に確認できます。

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

これは私の最初のテストで、3181桁のソリューションを検索しました。26秒で最初のケースが見つかりました。

推論を行ってみましょう。次に、プログラム自体にステップインします。

「450番目の素数とは何ですか?」その数の数字(3181)で解決策を見つけることができますか?

primeDigits = Prime[450]

3181


数字は数字を結合することで見つけられます。

number = FromDigits[digits];

しかし、それを表示するのではなく、代わりに数字が何で、どこにあるのかを尋ねることができます。

DigitCount[number]

{3180、0、0、0、0、0、1、0、0、0}

これは、数字1のインスタンスが3180個、数字7のインスタンスが1つあったことを意味します。

桁7はどの位置にありますか?

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

142

したがって、数字7は142桁目です。他のすべては1です。


もちろん、数字の積は素数、つまり7でなければなりません。

digitProduct = Times @@ digits

7


そして、数字の合計も素数です。

digitSum = Plus @@ digits
PrimeQ[digitSum]

3187
True


そして、桁数が素数であることを知っています。450番目の素数、つまり3118を選択したことを思い出してください。

したがって、すべての条件が満たされています。


3
誤解しない限り、その合計は4009であり、素数ではありません。
gerw 14

一つのこと:それは素数であり、桁数ではないすべての数字の合計であるべきではありませんか?あなたの場合4002 * 1 + 7 = 4009、仕様に従って4003ではなくテストする必要があります。
ジョンライド14

2
@Johnride:両方とも素数でなければなりません。
gerw

@gerw正しい。桁数、桁の合計、桁の積はすべて素数でなければなりません。
カルビンの趣味14

あなたはすべて正しかった。以前の提出では、素数の桁合計を確認するのを忘れていました。これは、次のいずれかが重要かどうかを確認することによって行われます(どちらでもかまいません):桁の長さ+2、桁の長さ_4、または桁の長さ+6。
DavidC 14

7

Python 2.7、6217桁:{23} 5 {6193} 6分51秒

私は自分のバージョンに取り組んでいて、is_(very_probably)_prime()であるにもかかわらず、@ issacgが非常によく似たアプローチで私を打ち負かしたことに失望しました。ただし、より短い時間でより良い回答を得ることができる(is_primeも使用する場合)いくつかの重要な違いがあることがわかります。これを明確にするため、4000から開始するとき、標準の Pythonインタープリター(バージョン2.7でも)ではなく、PyPy を使用して、わずか26分37秒でより良い4001桁の回答({393} 7 {3607})に到達しますバージョン。また、私は数字をチェックする「スポット」ではありません。すべての候補者がチェックされます。

主な改善点は次のとおりです。

  1. プライムジェネレーター(https://stackoverflow.com/questions/567222/simple-prime-generator-in-python/568618#568618)を使用して、チェックするプライムのリストを作成し、(「小さなプライム」のバージョン)適格な数の長さを生成します。

  2. 最小ではなく、与えられた長さの最大の素数を探すのに時間を費やしたいので、最小ではなく、最初にチェックのために可能な最大数を構築します。次に、1つが見つかったら、すぐに次の長さに移動できます。

編集:マルチプロセッシングで今

これは、以前のバージョンに対する重要な変更です。以前、8コアのマシンがほとんど機能していないことに気付いたので、Pythonでのマルチプロセッシング(初めて)を試すことにしました。結果はとても素晴らしいです!

このバージョンでは、7つの子プロセスが生成され、潜在的な可能性(num_length +適格な数字)のキューから「タスク」を取得します。彼らは、異なる[7,5,3]のポジションを見つけて、それが見つかるまで解き放ちます。存在する場合、見つかった新しい最長の長さをマスタープロセスに通知します。短いnum_lengthで作業している子供は、保釈し、次の長さを取得します。

私は6000でこの実行を開始し、まだ実行中ですが、これまでのところ、結果に非常に満足しています。

プログラムはまだ正しく停止していませんが、私にとっては大したことではありません。

今のコード:

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

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

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


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

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


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

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

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

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

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


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

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

    start_length = int(sys.argv[1])

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

    largest = Value('d', 0)

    task_generator = gen_tasks(start_length)

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


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

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

コードパッドリンクを[必要に応じて壊れた]インポートとして表すと読みやすくなります
Sparr 14

反対側のコードはそのように実際にはインポートできないため、これは混乱を招くと思います。
mkoistinen 14

isaacgの構文を使用します。URLにコメントしてから、存在しないパッケージ(この場合は
my_math

1
実際には、最大から最小の数値も生成します。私たちのコードの違いはあまり重要ではないと思います。違いは、コードよりもコンピューターにあると期待しています。それにもかかわらず、よくやった、そしてサイトへようこそ。
isaacg 14

my_mathまた、素数のリストを生成するためにも使用できwhile prime < 20006: prime = next_prime(prime)ます。の約3倍の速度でgen_primes、メモリ効率がはるかに高いようです。
primo 14

6

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

インスピレーションとトリックについて@issacgと皆さん全員に賞賛を。
また、この質問に対する@ Calvin's Hobbiesの質問者にも質問があります。

コンパイル: gcc -I/usr/local/include -o p_out p.c -pthread -L/usr/local/lib -lgmp

計算能力を寄付したり、パフォーマンスに興味がある場合は、コードをコピーしてコンパイルしてください。;)GMPをインストールする必要があります。

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

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

static void huntSupremePrime(int startIndex) {

    char digits[MAX_DIGITS + 1];

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

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

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

    int step = THREAD_COUNT * 2;

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

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

    }
}

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

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

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

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

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

    pthread_exit(NULL);
    return 0;
}

5

PFGW、6067桁、{5956} 7 {110}

次の入力ファイルでPFGWを実行し-f100、数値をプリファクタリングします。コンピューター(i5 Haswell)で約2〜3 CPU分で、PRP(10 ^(6073-6)-1)/ 9 + 6 * 10 ^ 110、または{5956} 7 {110}を見つけます。ノースリーブアップ番号として、以前のすべての提出よりも少し大きい6000桁を開始点として選択しました。

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

これをどれだけ早く見つけることができたかに基づいて、桁数を簡単に増やしても、1時間以内にPRPを見つけることができました。ルールが書かれている方法で、私もちょうど私のCPUは、すべての4つのコア上で実行して、時間に1 PRPテストを終えることができるサイズを見つけるかもしれない、取る長い私の「検索」をPRPを見つけるために時間を、と持っているだけで構成されて1つのPRPの。

PSある意味では、これは「コード」ソリューションではありません。入力ファイル以外には何も書いていないからです...しかし、数学的な問題に対する多くの1行のMathematicaソリューションは、同じように記述できます。あなたのために大変な仕事をするライブラリを使用する。現実には、両者の間に良い線を引くのは難しいと思います。必要に応じて、PFGW入力ファイルを作成してPFGWを呼び出すスクリプトを作成できます。このスクリプトは、4つのコアすべてを使用し、検索を(CPU上で)〜4倍高速化するために、並行して検索することもできます。

PPS LLRはこれらの数値に対してPRPテストを実行できると思いますが、PFGWよりもはるかに高速になると思います。専用のふるいプログラムは、PFGWの1つずつよりも、これらの数値を因数分解するのに優れている可能性があります。これらを組み合わせた場合、現在のソリューションよりもはるかに高い範囲をプッシュできると確信しています。


4

Python 2.7、17-19桁

11111111171111111

3秒で5111111111111(13桁)が見つかり、3分でこの17桁の最高素数が見つかりました。ターゲットマシンがこれを実行し、1時間以内に19桁の最高の素数を取得できると思います。このアプローチは、メモリ内のターゲット桁数の半分まで素数を保持するため、うまくスケールしません。17桁の検索には、100Mのブール値の配列を保存する必要があります。19桁には1B要素配列が必要であり、23桁に達する前にメモリが使い果たされます。ランタイムもおそらくそうでしょう。

途方もなく大きな除数の素数の配列を含まない素数性テストのアプローチは、はるかにうまくいくでしょう。

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

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

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

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

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

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

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

3

Mathematica 4211 4259桁

番号付き:{1042} 7 {3168} {388} 3 {3870}

次のコードで生成されました:

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

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

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

スローにより、現在見つかっている数字と同じ数字を持つ他の数字のテストが停止します。最上位桁でテストを開始するため、桁数が素数のトリプレットのメンバーでない限り、常に最大数が返されます。

上記の回答のいずれかの値のすぐ下のテストを開始しました。

終了すると、数値は変数curlargestに保存されます


2

JavaScript、3019桁、{2,273} 5 {745}

これは、Tom WuによるBigInteger.jsに含まれているMillerRabinテストを使用します。

1時間で0 => 2,046桁 = {1799} 7 {263} から始まります。

始まる3000 => 3,019桁 = {2,273} 5 {745} 1時間で、より少ない3秒

0から開始すると、プログラムは先にスキップし、最後に見つかったs-primeの長さの1.5倍の長さで再び検索を開始しました。それから私はそれがどれほど速く動くかを見たとき、1時間で3000から始まるものを見つけると思いました-それはわずか3秒の余裕でしました。

ここで試すことができます:http : //goo.gl/t3TmTk
(すべてのs-primesを計算するように設定するか、先にスキップします。)

ここに画像の説明を入力してください ここに画像の説明を入力してください
ここに画像の説明を入力してください

このプログラムは、すべて「1」の文字列を作成することで機能しますが、1つの「3」、「5」、または「7」を使用します。「5」で終わる番号を拒否するために、IsStrPrime関数にクイックチェックを追加しました。

if (IsIntPrime(length)) {

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

    if (do3s || do5s || do7s) {

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

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

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

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

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

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

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

これはとても楽しかったです。数字を削除したプライムと呼ばれるものを計算するために何年も前に行ったパズルを思い出します。これは、数字を削除しても残りの数が素数である素数です。たとえば、1037、037、137、107、および103は素数であるため、1037は数字を除いた素数です。私は84桁の長さを見つけましたが、私が知っている最長の長さは332桁です。このパズルに使用されているテクニックを使えば、もっと長いものを見つけることができると確信しています。(ただし、トライアル番号の選択は少し複雑です-多分?)


RE:数字は素数削除しましたここにあります。332桁も勝ったでしょう。
primo 14

0

公理、3019桁{318} 5 {2700}

)time on

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

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

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

529秒の開始値3000からの結果

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

   (4)
   [3019, 318, 5, 2700, Omissis]
                                            Type: List NonNegativeInteger
       Time: 0.02 (IN) + 525.50 (EV) + 0.02 (OT) + 3.53 (GC) = 529.07 sec
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.