Найдите наибольшее простое число, длина, сумма и произведение которого простое.


37

Число 113- это первое простое число, длина 3которого проста, цифровая сумма 5 = 1 + 1 + 3проста, а цифровое произведение 3 = 1 * 1 * 3простое.

Простое число, которое имеет эти 3 свойства, будет называться в высшей степени простым . Простые числа 11117и 1111151другие примеры.

Цель

Напишите программу, которая может найти наибольшее простое число, меньшее возможного, менее чем за час на приличном современном персональном компьютере (например, предпочтительная спецификация здесь ).

Вы не должны просто дать нам большое высшее премьер. Вы должны показать нам свой процесс поиска с кодом, который действительно работает. Вы можете опираться на свои или чужие решения, но обязательно им следует отдать должное. Мы как бы пытаемся совместно найти самый большой главный реализм на обычном компьютере за час.

счет

Представление, которое находит самый большой верхний премьер выигрывает. Если окажется, что конечных простых чисел конечное число, то первое подчинение, которое порождает высшие простые первичные выигрыши, выигрывает.

(Если вы можете математически доказать, что существует или не существует бесконечно много высших простых чисел, я дам вам 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}.


Можем ли мы начать со списка простых чисел или получить список из Интернета и потратить час на проверку превосходства?
Спарр

2
Если вы можете начать с самого высокого из известных высших простых чисел, то это становится проблемой для тех, кто может написать программу, которая тратит ровно час, охватывающий максимально возможный разрыв между двумя высшими простыми числами. :(
Спарр

8
Помимо отсутствия 0, любое потенциальное высшее простое число, очевидно, должно иметь вид 1 ^ n [3 | 5 | 7] 1 ^ m, т. Е. Несколько единиц, любое простое число ниже 10 и еще несколько единиц. Есть больше ограничений, которые вы можете наложить прямо сейчас.
Инго Бюрк

3
Райан начал связанный с MSE вопрос о существовании бесконечного числа высших простых чисел. Если у вас есть какие-либо идеи по этому вопросу, пожалуйста, взвесьте!
квазиклассический

1
Я легко могу показать, что в настоящее время нет доказательства бесконечного числа высших простых чисел (и что для этого потребовалось значительное количество работы). Согласно michaelnielsen.org/polymath1/… , мы знаем, что простые числа приходят бесконечно с промежутками, такими как 246, но для доказательства бесконечных верхних простых чисел нам нужен промежуток 2, 4 или 6 (соответствующий простым числам с 3, 5 или 7 где-то в них).
Тим С.

Ответы:


9

Perl, 15101 цифр, {83} 7 {15017}, 8 минут. Макс найдено: 72227 цифр

Используя мой модуль Math :: Prime :: Util и его GMP-сервер . Он имеет ряд тестов на композитность, в том числе is_prob_prime () с тестом ES BPSW (немного более строгим, чем ispseudoprime Пари), is_prime (), который добавляет одну случайную базу MR, и is_provable_prime (), которая будет запускать BLS75 T5 или ECPP. При таких размерах и типах доказательство займет много времени. Я бросил еще один тест MR в сабвуфере верификатора. Время от времени на Core2 E7500, который определенно не самый быстрый мой компьютер (на моем i7-4770K это занимает 2,5 минуты).

Как указывает Тим ​​С., мы можем продолжать поиск больших значений, вплоть до момента, когда один тест занимает час. При значении ~ 15000 цифр на этом E7500 требуется около 26 с для теста MR и 2 минуты для полного is_prime (пробное деление плюс базовое 2 MR плюс ES Lucas плюс одно случайное базовое MR). Мой i7-4770K более чем в 3 раза быстрее. Я попробовал несколько размеров, в основном, видя, как это было на результаты других людей. Я пробовал 8k, 20k и 16k, убивая каждого через ~ 5 минут. Затем я пробовал 15к в прогрессии по ~ 10м каждый и мне повезло на 4-м.

PRP-тесты OpenPFGW, безусловно, быстрее, чем после 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}

Для результата с 32-значным числом я запустил 6 сценариев, запущенных одновременно, каждый с последовательными аргументами, начинающимися с 32000. Через 26,5 минут один закончил с показанным результатом с 32063-значным результатом. Для 57k я позволял последовательным сценариям запускаться по 6 раз в течение часа с шагом ввода 500, пока результат 57k не вернется через 57 минут. Результат из 72 тыс. Цифр был найден путем выполнения последовательных простых чисел от 70 тыс., Поэтому определенно не найден через час (хотя, как только вы знаете, с чего начать, это так).

Сценарий:

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

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

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111113111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

Нашел это примерно через 50 минут после начала с 4000. Поэтому я бы оценил, что это верхний предел этого подхода кода.

Изменение: я заметил, что некоторые длины кажутся более плодотворными для генерации такого простого числа, чем другие, поэтому я решил проверить только 50 случайных положений цифры, которые не равны 1, вместо всех возможных положений перед перемещением на. Я не совсем уверен, что это улучшит производительность, или что 50 - это правильно, но посмотрим.

Список возможностей формируется на основе того факта, что для выполнения требования к продукту число должно быть все, кроме простого. Кроме того, простое число не может быть 2 из-за отношения суммы и длины, а цифровая сумма не должна делиться на три, что соответствует требованиям% 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/… Первый ответ
Исаак

Ну тогда. Я тебе кредит.
Исаак

10
Это как ASCII, где Уолли ...
Трихоплакс

5
Может быть, вам следует переименовать функцию is_very_very_very_very_very_very_very_probably_prime()...
trichoplax

2
Mathmatica и Maple используют один и тот же метод, так что не все так плохо.
Примо

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)

Это заняло 36 минут, чтобы вычислить на одном ядре довольно старой машины. Я уверен, что найти такое простое число из 5000 цифр в час не составит труда, но я также нетерпелив.

Лучшим решением было бы использовать любой разумный язык для выполнения всего, кроме самого внутреннего цикла, а затем создать файл abc для простой формы, оптимизированный для этого конкретного вида вычислений. Это должно быть в состоянии подтолкнуть расчет по крайней мере до 10000 цифр.

Изменить : я реализовал гибридное решение, описанное выше, но на моей старой машине я не могу найти первый термин с> = 10000 цифр менее чем за час. Если я не запускаю его на чем-то более быстром, мне придется перейти на менее высокую цель.


Как вы узнали, чтобы начать в 4100?
Исаак

@isaacg: Я просто пытался быть больше, чем (неправильное) решение Mathematica, которое было чуть больше 4000. Я просто перешел к следующему кратному 100, как число «ничего-до-моего-рукава». На самом деле кажется, что это было неудачное начало, так как мне пришлось идти дольше, чем я ожидал (и дольше, чем Mathematica!), Чтобы найти простое число.
Чарльз

Нет, вообще-то, тебе невероятно повезло. (4127,3) - первая пара после 4100, и по чистой случайности она имеет простое число. У многих пар вообще нет простых чисел.
Исаак

@isaacg: Может быть и так. Моя эвристика явно отключена, так как я ожидал, что вероятность ~ 80% найти простое число в данной паре: 1 - exp (-15 / (4 * log 10)), но они кажутся более редкими, поэтому они не действуйте как случайные {2, 3, 5} -гладкие числа их размера (если я не лукавлю в вычислениях).
Чарльз

@isaacg: В любом случае я работаю над «лучшим решением», которое я упомянул сейчас: перенести тяжелую работу на pfgw. Он искал первые 20 пар выше 10 ^ 10000, не найдя ничего, но это заняло ~ 15 минут.
Чарльз

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}

Это означает, что было 3180 экземпляров цифры 1 и один экземпляр цифры 7.

В каком положении находится цифра 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

Одна вещь: не должна ли быть сумма всех цифр, которые просты, а не количество цифр? В вашем случае вам придется тестировать, 4002 * 1 + 7 = 4009а не 4003 в соответствии со спецификацией.
Джонрайд

2
@Johnride: оба должны быть простыми.
рос

@gerw это правильно. Количество цифр И сумма цифр И произведение цифр должны быть простыми.
Увлечения Кэлвина

Вы все были правы. В моем более раннем представлении я забыл проверить сумму цифр на простоту. Теперь это делается путем определения, является ли одно из следующего (неважно, какое) простым: длина цифры + 2, длина цифры _4 или длина цифры +6.
DavidC

7

Python 2.7, 6217 цифр: {23} 5 {6193} 6 минут 51 секунда

Я работал над своей собственной версией и был разочарован, увидев, что @issacg избил меня до отказа с помощью очень похожего подхода, хотя и с is_ (very_probbly) _prime (). Тем не менее, я вижу, что у меня есть некоторые существенные различия, которые приводят к лучшему ответу за меньшее время (когда я также использую is_prime). Чтобы прояснить это, когда я также начинаю с 4000, я получаю лучший 4001-значный ответ ({393} 7 {3607}) всего за 26 минут, 37 секунд, используя стандартный интерпретатор Python (также в версии 2.7), а не 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

используйте синтаксис isaacg. закомментируйте URL, затем импортируйте из несуществующего пакета (my_math, в его случае)
Sparr

1
На самом деле, я генерирую числа от самых больших до самых маленьких. Я не думаю, что наши различия в коде очень значительны. Я ожидаю, что разница будет лежать больше в наших компьютерах, чем в нашем коде. Тем не менее, молодцы, и добро пожаловать на сайт.
Исаак

my_mathтакже может быть использован для создания списка простых чисел, а ля while prime < 20006: prime = next_prime(prime). Кажется, примерно в 3 раза быстрее gen_primes, и гораздо более эффективно использовать память.
Примо

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введите числа. Примерно через 2-3 минуты процессора на моем компьютере (i5 Haswell) он находит 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 ядрах, может завершить один тест PRP за час, занять много времени, чтобы найти PRP, и мой поиск будет состоять исключительно одного PRP.

PS В некотором смысле это не «кодовое» решение, потому что я ничего не написал, кроме входного файла ... но тогда многие однострочные решения математических задач Mathematica можно было бы описать так же, как и используя библиотеку, которая делает тяжелую работу за вас. На самом деле, я думаю, что трудно провести хорошую черту между ними. Если хотите, я мог бы написать скрипт, который создает входной файл PFGW и вызывает PFGW. Скрипт может даже выполнять поиск параллельно, использовать все 4 ядра и ускорить поиск в ~ 4 раза (на моем процессоре).

PPS Я думаю, что LLR может выполнить тесты PRP для этих чисел, и я ожидаю, что это будет намного быстрее, чем PFGW . Специальная программа просеивания могла бы также лучше учитывать эти цифры, чем PFGW по одному. Если бы вы объединили их, я уверен, что вы могли бы раздвинуть границы намного выше, чем существующие решения.


4

Python 2.7, 17-19 цифр

11111111171111111

Найдено 5111111111111 (13 цифр) за 3 секунды и это 17-значный высший штрих за 3 минуты. Я предполагаю, что целевая машина может запустить это и получить 19-значное простое число за менее чем час. Этот подход плохо масштабируется, потому что он сохраняет простые числа до половины количества целевых цифр в памяти. 17-значный поиск требует хранения массива 100M логических. Для 19 цифр потребуется массив элементов 1B, и память будет исчерпана до получения 23 цифр. Runtime, вероятно, тоже будет.

Подходы теста простоты, которые не включают в себя смехотворно большой массив простых делителей, будут намного лучше.

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

Для этого используется тест MillerRabin, включенный в BigInteger.js Томом Ву.

Начиная с 0 => 2 046 цифр = {1799} 7 {263} за один час .

Начиная с 3000 => 3,019 цифр = {2,273} 5 {745} за один час, менее 3 секунд .

Когда он начался с 0, программа пропустила его и снова начала поиск на длине 1,5Х длины последнего найденного s-простого числа. Затем, когда я увидел, насколько быстро он работает, я догадался, что он найдет один, начинающий с 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: цифра удалена, у нас это было . 332 цифры тоже выиграли бы.
Примо

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

результат от начального значения 3000 за 529 с

(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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.