Знайдіть найбільший прайм, довжина, сума та добуток є простим


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, тобто деякі 1s, будь-який простір нижче 10 та ще декілька 1s. Є більше обмежень, які ви можете накласти на них відразу.
Інго Бюрк

3
Ryan почав пов'язане питання з MSE щодо існування нескінченно багатьох верховних праймес. Якщо у вас є питання щодо цього питання, будь ласка, зважте!
півкласика

1
Я легко можу довести, що наразі немає доказів нескінченної кількості верховних праймерів (і на те, що велика кількість робіт пішла назустріч цьому). Згідно з michaelnielsen.org/polymath1/… , ми знаємо, що прайми йдуть нескінченно разом із проміжками, як 246, але для підтвердження нескінченних верховних прайменів нам потрібен проміжок 2, 4 або 6 (відповідає праймем з a 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 або ЄКПТ. За таких розмірів і типів робити доказ потрібно багато часу. Я кинув ще один тест на МР у підгрунті педантичного верифікатора. Часи на Core2 E7500, який, безумовно, не є моїм найшвидшим комп'ютером (це займає 2,5 хвилини на моєму i7-4770K).

Як зазначає Тім С., ми могли б продовжувати пошук більших значень, аж до часу, коли один тест займає годину. При ~ 15000 розрядів на цьому E7500 потрібно близько 26 секунд для проведення тесту на МР та 2 хвилини для повного значення_процесу (пробний поділ плюс база-2 МР плюс ES Лукас плюс один випадковий базовий МР). Мій 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 цифр. Протягом 57 кб я дозволяв послідовним сценаріям працювати 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 разів або більше (куди до Пари / ГП для безлічі чудових ідей). Я завжди ціную відгуки, тому повідомте мені, якщо щось працює не так, як вам хотілося.
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/… Перша відповідь
isaacg

Тоді гаразд. Я вам зарахую.
isaacg

10
Це як ASCII, де wally ...
trichoplax

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-файл для primeform, який оптимізований для конкретного виду обчислення. Це має бути спроможним підсунути обчислення не менше ніж до 10000 цифр.

Редагувати : я реалізував гібридне рішення, описане вище, але на своїй старій машині я не можу знайти перший термін з> = 10000 цифрами менше ніж за годину. Якщо я не запускаю його на щось швидше, мені доведеться перейти на менш високу ціль.


Звідки ви знали, що починати з 4100?
isaacg

@isaacg: Я просто намагався бути більшим, ніж (неправильне) рішення Mathematica, яке було трохи більше 4000. Я просто перейшов до наступного кратного 100, як номер "нічого вгору". Насправді здається, що це було нещасливим початковим місцем, оскільки мені довелося пройти довше, ніж я очікував (і довше, ніж Mathematica!), Щоб знайти прайм.
Чарльз

Ні, насправді, вам неймовірно пощастило. (4127,3) - перша пара після 4100 р., І, звичайно, випадково вона є простою. Багато пар взагалі не мають прем'єр-міністра.
isaacg

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

@isaacg: У будь-якому випадку я працюю над «кращим рішенням», про яке я вже згадував: підштовхуючи важку роботу до pfgw. Шукали перші 20 пар вище 10 ^ 10000, не знайшовши нічого, але це зайняло ~ 15 хвилин.
Чарльз

7

Математика 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
Правда


І ми знаємо, що кількість цифр - найголовніше. Пам'ятайте, ми обрали 450-й прем'єр, а саме 3118.

Тож усі умови були виконані.


3
Якщо я не помиляюся, його сума становить 4009, що не є простим.
герв

Одне: чи не має бути сума всіх цифр найпростішою, а не кількість цифр? У вашому випадку вам доведеться протестувати4002 * 1 + 7 = 4009 а не 4003 відповідно до специфікації.
Johnride

2
@Johnride: Обидва повинні бути прем'єр-міністром.
герв

@gerw правильно. Кількість цифр І сума цифр І добуток цифр усі повинні бути простими.
Захоплення Кальвіна

Ви всі були правильні. У своїх попередніх поданнях я забув перевірити цифру суми на предмет первинності. Тепер це робиться, дізнавшись, чи є одним із наступних (не важливо, який) простим: довжина цифри + 2, довжина цифри _4 або довжина цифри +6.
DavidC

7

Python 2.7, 6217 цифр: {23} 5 {6193} 6 хв 51 сек

Я працював над моєю власною версією і розчарувався, побачивши, що @issacg побив мене до удару дуже схожим підходом, хоча і з is_ (very_probably) _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] позицій, поки не знайдуть її. Якщо це так, повідомляє головний процес про нову найдовшу довжину, яку було знайдено. Якщо діти працюють на коротшій довжині, вони просто піддаються під заставу та йдуть на наступну довжину.

Я розпочав цей пробіг з 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
Насправді я також генерую числа від найбільших до найменших. Я не думаю, що наші кодові відмінності є дуже істотними. Я б очікував, що різниця лежить більше на наших комп’ютерах, ніж у нашому коді. Тим не менше, молодець, і ласкаво просимо на сайт.
isaacg

my_mathможе також використовуватися для створення списку простих чисел, а-ля while prime < 20006: prime = next_prime(prime). Здається, це в 3 рази швидше gen_primesі набагато ефективніше пам'яті.
прим

6

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

Кудо, щоб @issacg та всі ви, хлопці, для натхнення та хитрощів.
А також майстерне запитання @ Хобі Кальвіна щодо цього питання.

Збірка: 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, і щоб мій "пошук" складався виключно одного ПРП.

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-значний пошук вимагає зберігання масиву з 100 М булів. На 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

Математика 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]

Кидки змушують припинити тестування інших чисел з тими ж цифрами, що і наразі знайдений. оскільки він починає тестування на найбільш значущій цифрі, це означатиме, що він завжди повертає найбільшу кількість, якщо кількість цифр не є членом простієї триплети.

Просто розпочали тестування трохи нижче значення однієї з попередніх відповідей :)

Після того, як воно закінчиться, число зберігається у змінній величині


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,5X довжину останнього знайденого s-prime. Тоді, коли я побачив, як швидко це біжить, я здогадався, що знайде одного, починаючи з 3000 за одну годину - що це зробило лише 3 секунди, щоб запасти.

Ви можете спробувати тут: http://goo.gl/t3TmTk
(Встановіть для обчислення всіх s-primes або пропустіть вперед.)

введіть тут опис зображення введіть тут опис зображення
введіть тут опис зображення

Програма працює, будуючи рядки з усіх "1" s, але з одним "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.