查找最大素数,其长度,总和与素数为素数


37

数字113是第一个素数,其长度3为素数,数字和5 = 1 + 1 + 3为素数,数字乘积3 = 1 * 1 * 3为素数。

具有这三个属性的素数将称为至尊素数。质数111171111151是其他示例。

目标

编写一个程序,可以在一台像样的现代个人计算机上在不到一个小时的时间内找到最大的最大数(例如此处的首选规范)。

您不应该简单地给我们提供最高的质数。您需要使用有效的代码向我们展示您的搜索过程。您可以基于您或其他人的解决方案,但请务必给予他们好评。我们通常是想在一个小时内找到可在普通计算机上实现的最大最高质数。

计分

找到最大的首要胜利的提交。如果事实证明存在无限多个最高素数,则第一个提交的最高素数获胜。

(如果您可以从数学上证明有无数个至尊素数,我会仅仅因为这个而给您200个赏金代表。:))

细节

  • 您可以使用任何来源生成素数(例如,互联网)。
  • 您可以使用概率素数测试方法。
  • 一切都在基数10中。
  • 零和一不视为质数。
  • 包含0的素数具有0如此明显的数字产品,它们不可能是至高无上的。
  • 为了使页面更整洁,请使用以下格式添加大(100位数以上)最高质数:

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

    因此1111151可以表示为{5}5{1}


我们可以从素数列表开始还是从互联网上获取列表,然后花一个小时进行最高性检查?
Sparr 2014年

2
如果您可以从已知的最高质数开始,那么这对于谁可以编写一个程序花费正好一个小时跨越两个最高质数之间最大的差距就成为了一个挑战。:(
Sparr 2014年

8
除了不包含0之外,任何潜在的最高质数显然都必须具有1 ^ n [3 | 5 | 7] 1 ^ m的形式,即一些1s,任何低于10的质数和更多的1s。您可以立即施加更多限制。
IngoBürk,2014年

3
瑞安(Ryan)对MSE提出了一个相关的问题,即存在无数个至尊素数。如果您对该问题有任何见解,请权衡一下!
2014年

1
我可以很容易地证明,目前尚无无限数量的至尊素数的证明(并且已经进行了大量工作)。根据michaelnielsen.org/polymath1/…的知识,我们知道质数无限地伴随着最小为246的间隙,但是要证明无限至尊质数,我们需要2、4或6的间隙(对应于在其中某处的3、5或7)。
Tim S.

Answers:


9

Perl,15101位数字,{83} 7 {15017},8分钟。最多找到:72227位

使用我的模块Math :: Prime :: Util及其GMP后端。它具有许多综合性测试,包括带有ES BPSW测试的is_prob_prime()(比Pari的ispseudoprime严格得多,添加了一个随机基MR的is_prime()和将运行BLS75 T5或ECPP的is_provable_prime()。在这些大小和类型下,进行证明将需要很长时间。我在学究验证器子目录中进行了另一个MR测试。使用Core2 E7500的时间肯定不是我最快的计算机(在i7-4770K上需要2.5分钟)。

正如Tim S.指出的那样,我们可以继续搜索更大的值,直到一次测试需要一个小时的时间。此E7500上的数字约为15000,进行MR测试大约需要26秒,而完整的is_prime(试算加上基数为2的MR加ES卢卡斯加上一个随机基数的MR)大约需要2分钟。我的i7-4770K快3倍以上。我尝试了几种尺寸,主要是看它如何影响其他人的结果。我尝试了8k,20k和16k,在大约5分钟后将其杀死。然后,我尝试了15k进行中,每次约10m,并在第4个上很幸运。

一旦超过4000位左右,OpenPFGW的PRP测试无疑会更快,而在50k +范围内,确实要快得多。然而,它的测试有相当多的误报,这使其成为一个很好的预测试,但仍然想用其他方法来验证结果。

这可以与perl线程并行化,也可以使用MCE来实现,类似于模块中的并行Fibonacci prime finder示例。

使用单核的空闲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,我让连续的脚本一次运行6,一个小时,输入增量为500,直到57k的结果在57分钟内返回。72k位数字的结果是通过从70k开始进行连续的质数运算得到的,因此绝对不可能在一小时内找到(尽管一旦您知道从哪里开始,它就可以了)。

剧本:

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

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

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

+1向我介绍这个图书馆!我的机器上的素数迭代时间小于10 ^ 7(与CPython使用gmpy2,和PyPy使用my_math)相比:codepad.org/aSzc0esT
primo

很高兴你喜欢它!还有其他方法,包括forprimes { ...do stuff... } 1e7;速度提高10倍或更多(对Pari / GP表示赞扬的是许多很棒的主意)。我总是很感激您的反馈,所以请让我知道是否有某些事情无法按照您希望的方式进行。
DanaJ

21

PyPy上的Python 2.7,{2404} 3 {1596}(〜10 ^ 4000)

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111113111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

从4000开始大约50分钟后发现了这一代码。因此,我估计这是此代码方法的上限。

更改:我注意到,某些长度似乎比其他长度更能产生这种质数,因此我决定在移动之前仅检查50个不是1的数字的随机位置,而不是所有可能的位置上。我不完全确定这会提高性能,还是50个是正确的,但是我们会看到的。

可能性列表是基于以下事实生成的:要满足产品要求,编号必须是全数(撇号除外)。另外,由于和和长度的关系,素数不能为2,并且数字和不能被3整除,给出%3的要求。

is_prime取自http://codepad.org/KtXsydxK,由@primo编写

注意:此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 2014年

好吧。我相信你
isaacg 2014年

10
就像ASCII一样,这
里面很薄

5
也许您应该重命名该函数is_very_very_very_very_very_very_very_probably_prime()……
trichoplax 2014年

2
MathmaticaMaple都使用相同的方法,因此不会那么糟。
primo 2014年

13

PARI / GP,4127位

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

这是一个非常简单的搜索:仅检查素数位数的长度,然后计算要使用的素数,然后遍历所有可能性。我对使用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)

在相当老的计算机的一个内核上进行计算需要36分钟。我敢肯定,在一个小时内找到这样一个超过5000位数的质数是没有问题的,但是我也不耐烦。

更好的解决方案是使用任何合理的语言来执行除最内层循环以外的所有操作,然后为primeform构造一个abc文件,该文件针对该特定种类的计算进行了优化。这应该能够将计算推到至少10,000个数字。

编辑:我实现了上述混合解决方案,但是在我的旧机器上,我不到一个小时就找不到带有> = 10,000位数的第一个术语。除非我以更快的速度运行它,否则我将不得不更改为一个不太崇高的目标。


您怎么知道从4100开始?
isaacg 2014年

@isaacg:我只是在尝试大于(不正确的)Mathematica解决方案,后者刚好超过4000。我只是以“ nothing-up-my-sleeve”的数字进入了100的下一个倍数。实际上,这似乎是一个不幸的起点,因为要想找到素数,我必须比我预期的时间更长(并且比Mathematica更长!)。
2014年

不,实际上,您真幸运。(4127,3)是4100年之后的第一对货币对,而且碰巧有一个素数。很多对根本没有素数。
isaacg 2014年

@isaacg:也许是。我的启发式方法显然不可行,因为我期望在给定对中找到素数的概率约为80%:1-exp(-15 /(4 * log 10)),但它们似乎比这稀少,因此不要像它们的大小的随机{2,3,5}-光滑数字那样操作(除非我对计算有误解)。
2014年

@isaacg:无论如何,我正在研究我现在提到的“更好的解决方案”:将艰苦的工作推向pfgw。它搜索了10 ^ 10000以上的前20对,但没有找到任何东西,但这只花了大约15分钟。
2014年

7

Mathematica 3181位数字

更新:我的第一次提交中有一些严重的错误。我能够花一​​些时间检查这一结果。输出格式为数字列表。这样可以轻松检查每个条件。

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

这是我的第一个测试,寻找具有3181位数字的解决方案。它在26秒内发现了第一例。

让我们进行推理。然后,我们将进入程序本身。

让我们像我一样开始说:“第450个素数是什么?” 我们能找到这么多位数的解决方案(3181)吗?

primeDigits = Prime[450]

3181


通过连接数字找到数字。

number = FromDigits[digits];

但是,除了显示它,我们还可以询问数字是什么以及它们在哪里。

DigitCount[number]

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

这意味着数字1有3180个实例,数字7有一个实例。

数字7在什么位置?

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

142

因此,数字7是第142位数字。所有其他均为1。


当然,数字的乘积必须是质数,即7。

digitProduct = Times @@ digits

7


而且数字的总和也是素数。

digitSum = Plus @@ digits
PrimeQ[digitSum]

3187


而且我们知道位数是质数。请记住,我们选择了第450个素数,即3118。

因此,所有条件都已得到满足。


3
如果我没记错的话,它的总和是4009,这不是素数。
gerw 2014年

一件事:难道不是所有数字的总和是素数而不是数字的位数吗?在您的情况下,您将必须进行测试,4002 * 1 + 7 = 4009而不是根据规格进行4003 测试。
约翰里德(Johnride)2014年

2
@Johnride:两者都应该是素数。
gerw 2014年

@gerw是正确的。数字的位数,数字的总和以及数字的乘积都必须是质数。
卡尔文的爱好2014年

你们都是正确的。在我较早的提交中,我忘记了检查数字和是否为素数。现在,通过查看以下任一(无关紧要)是否为质数来完成此操作:数字长度+2,数字长度_4或数字长度+6。
DavidC 2014年

7

Python 2.7,6217位数字:{23} 5 {6193} 6分钟51秒

我正在使用自己的版本,但很失望地看到@issacg用非常相似的方法击败了我,尽管使用了is_(very_probably)_prime()。但是,我发现我有一些明显的差异,可以在更短的时间内得到更好的答案(当我也使用is_prime时)。为了清楚起见,当从4000开始时,我使用标准的 Python解释器(也是2.7版)仅用26分钟37秒就能得到更好的4001位数字答案({393} 7 {3607} ),而不是 PyPy版。另外,我不是“现场”检查数字。所有候选人都经过检查。

这是主要的改进:

  1. 使用素数生成器(https://stackoverflow.com/questions/567222/simple-prime-generator-in-python/568618#568618)创建要检查的素数列表(和他的“小素数”版本)并生成合格的号码长度。

  2. 我们想花时间寻找给定长度的最大素数,而不是最小素数,因此,我首先构造了可能的最大数进行检验,而不是最小。然后,一旦找到一个,我们可以立即继续进行下一个长度。

编辑:现在进行多处理

这是对先前版本的重大更改。以前,我注意到我的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

我认为那会令人困惑,因为另一端的代码并不是真的可以那样导入。
mkoistinen 2014年

使用isaacg的语法。注释URL,然后从不存在的包中导入(my_math,以他为例)
Sparr

1
实际上,我也会生成从最大到最小的数字。我认为我们的代码差异不是很大。我希望差异更多地在于我们的计算机而不是我们的代码。不过,做得很好,欢迎访问该网站。
isaacg

my_math也可以用于生成素数列表àla while prime < 20006: prime = next_prime(prime)。似乎速度大约是的3倍gen_primes,并且内存效率更高。
2014年

6

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

感谢@issacg和所有这些人的启发和技巧。
还有一个极好的问题,问这个问题的提问者是@ Calvin's Hobby。

编译: 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

根据我能够找到该密码的速度,我可以轻松地增加位数,并在一小时内仍找到PRP。关于规则的编写方式,我什至可能只找到运行在所有4个内核上的CPU可以在一个小时内完成一次PRP测试,花长时间才能找到PRP并让我的“搜索”完全包含在内的大小。一个PRP中的一个。

PS从某种意义上讲,这不是“代码”解决方案,因为除了输入文件外我什么也没写...但是,然后,可以用相同的方式描述许多针对数学问题的单行Mathematica解决方案,使用可以为您完成辛苦工作的库。实际上,我认为很难在两者之间划清界限。如果愿意,我可以编写一个脚本来创建PFGW输入文件并调用PFGW。该脚本甚至可以并行搜索,以使用所有4个内核,并将搜索速度提高约4倍(在我的CPU上)。

PPS我认为LLR可以对这些数字进行PRP测试,我希望它会比PFGW快得多。专用的筛选程序也可能比PFGW的一次筛选更好。如果将这些结合起来,我相信您可以将界限推到比当前解决方案高得多的水平。


4

Python 2.7,17-19位数字

11111111171111111

在3秒钟内找到5111111111111(13位),并在3分钟内找到17位最高质数。我猜目标计算机可以运行此程序并在不到一个小时的时间内获得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测试。

一小时内0 => 2,046位数 = {1799} 7 {263}开始。

3000 => 3,019位 = {2,273} 5 {745}开始,在一小时内,减去3秒

当从0开始时,程序向前跳过,并以发现的最后一个S素数的1.5倍的长度重新开始搜索。然后,当我看到它运行的速度有多快时,我猜它会在一小时内找到一个从3000开始的齿轮-剩下的时间只有3秒钟。

您可以在这里尝试:http : //goo.gl/t3TmTk
(设置为计算所有s-素数,或向前跳过。)

在此处输入图片说明 在此处输入图片说明
在此处输入图片说明

该程序通过构造全部为“ 1”但带有一个“ 3”,“ 5”或“ 7”的字符串来工作。我在IsStrPrime函数中添加了快速检查,以拒绝以“ 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;
        }
    }
}

这很有趣。让我想起了我很多年前计算数字去除素数的难题。这是素数,如果您删除任何数字,则其余数字仍为素数。例如,1037是除去了数字的质数,因为1037、037、137、107和103是质数。我发现一个84位数字长,而我知道的最长是332位数字。我敢肯定,使用此难题的技术可以找到更长的时间。(但是选择试用编号比较棘手-也许吗?)


RE:digit删除了质数,我们这里有一个。332个数字也将赢。
2014年

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.