Програма, яка знайде наступне просте число


15

Вступ:


Ви випадково зіпсували потік часу пристроєм, який ви зробили для розваги, який виявився машиною часу. Як результат, вас відсунули у далеке майбутнє. Ви зрозуміли, що обчислення, потужність обробки та комп'ютери загалом розвивалися величезною кількістю, щоб бути нескінченною точністю . Таким чином, ви захоплюєте себе комп’ютером з нескінченною пам’яттю та потужністю обробки. Ви поняття не маєте, як воно може мати нескінченну пам'ять і нескінченну потужність обробки, але ви просто приймаєте її і повертаєтесь до сучасності.

Виклик:


Ви чули, що людина, яка виявила найбільшого на даний момент прем'єр-міністра, 2^74,207,281 − 1отримала 100 000 доларів. Ви вирішили скласти програму, яка знайде наступний простір, оскільки ви хочете повернути гроші, витрачені на комп’ютер. Ви робите той, який приймає введення числа, і знаходить наступне просте число, або шляхом грубої сили, або будь-якого іншого методу.

Уточнення: у вас гіпотетична машина з нескінченною пам’яттю та потужністю обробки. Ваша програма НЕ МОЖЕ бути обмеженою (наприклад: C # 's int's може зберігатися від -2,147,483,648до 2,147,483,647), а ваша програма повинна мати можливість зберігати та працювати з будь-якою кількістю будь-якого розміру. У вас є нескінченні ресурси, тож вам не варто хвилюватись, чи не вистачило б вам пам’яті, якщо б ви це дозволили.

Приклад вводу / виводу:
Введення: Найбільший виявлений в даний час прайм з 22,338,618 цифрами.
Вихід: саме наступний розквіт

Очевидно, що вам не доведеться доводити, що це працює, оскільки для обчислення у фізичній машині знадобиться багато часу. Але якщо ви перенесли програму на гіпотетичну машину з нескінченною потужністю / пам’яттю, вона повинна обчислити миттєво.


Знайти наступний простір і перевірити, чи число є простим, це дві абсолютно різні речі


1
Це має бути конкретно наступним прем'єр-міністром ? Багато алгоритмів просте пошуку великих прайменів шукають лише певні типи чисел, а тому іноді пропускають
— простыні

10
Я думаю, вам слід додати кілька серйозних тестових випадків.
— FlipTack

3
" Ваша програма НЕ МОЖЕ бути обмеженою ", але, виходячи з прикладу, я підозрюю, що кожна наявна мова вважається обмеженою, якщо не підходить інша причина, ніж використання обмеженого типу для адреси пам'яті.
— Пітер Тейлор


2
@ mbomb007 чому? Усі відповіді, за винятком вбудованих, просто додають додаткову обгортку.
— Опублікувати Rock Garf Hunter

Відповіді:



8

Python 3 , 45 байт

f=lambda n,k=1,m=1:m%k*k>n or-~f(n,k+1,m*k*k)

Спробуйте в Інтернеті!


3
Я вважаю, що це теорема Вілсона у масках. kдорівнює кінцевому результату, mмістить (k-1)!^2. Оскільки (k-1)! = -1 mod k виконується лише тоді, коли k є простим, маємо (k-1)! (K-1)! = 1 мод k, який при множенні на k буде сам k. Ви обчислюєте квадрат, щоб позбутися єдиного винятку (k-1)! = 0 mod k для складеного k, що зустрічається при k = 4. Правильно?
— orlp

Так, це правильно.
— Денніс

Це кидає RecursionError: maximum recursion depth exceeded in comparisonдляf(1000)
— ов

5
@ovs Питання говорить про те, що ми маємо нескінченну пам’ять. Тому ми можемо припустити нескінченно високу межу глибини рекурсії, і, таким чином, не хвилюватися RecursionError.
— FlipTack

6

Python 2, 78 77 76 74 байт

def f(n):
 while 1:
    n+=1
    if[i for i in range(1,n)if n%i<1]==[1]:return n

-1 байт завдяки @KritixiLithos
-1 байт завдяки @FlipTack
-2 байти завдяки @ElPedro


n%i<1коротше, ніжn%i==0
— Kritixi Lithos

Після цього вам не потрібно пробілу if.
— FlipTack

Я думаю, ти маєш на увазі<1
— Джонатан Аллан

Я думаю, ви можете використовувати вкладку замість 2 пробілів для відступів другого рівня, але наразі я не можу перевірити.
— ElPedro

1
@ElPedro має рацію. Ви можете змінити два пробіли перед n+=1та ifна вкладки та зберегти 2 байти



4

Bash + coreutils, 52 байти

for((n=$1,n++;`factor $n|wc -w`-2;n++)){ :;};echo $n

Спробуйте в Інтернеті!

Документація bash та множника не визначає максимальне ціле значення, з яким вони можуть працювати (хоча, на практиці, кожна реалізація має максимальне ціле значення). Імовірно, у GNU майбутнього на ваших нескінченно великих машинах, bash та множник матимуть цілі числа необмеженого розміру.


Насправді документи задають для фактору, що якщо побудовано без gnu mp, підтримується лише одна точність.
— Dani_l

1
@Dani_l Добре, що людина в записі bash говорить лише: "Оцінка проводиться в цілих числах фіксованої ширини без перевірки на переповнення, хоча ділення на 0 знаходиться в пастці і позначено як помилка". Він не визначає ширину. (Як я пам’ятаю, біржові реалізації bash на моїх машинах використовують 64-бітні цілі числа, але зараз я не можу перевірити.) Що стосується фактора, він, безумовно, буде оновлений: майбутні комп'ютери OP з нескінченними ресурсами матимуть фактор компілюється з gnu_up, щоб отримати необмежену точність :).
— Мітчелл Спектор

3

Максима, 10 байт

next_prime

Функція повертає найменший прайм, більший за його аргумент.



3

Пітон із симпатією, 28 байт

import sympy
sympy.nextprime

sympy.nextprimeце функція, яка виконує те, що написано на жерсті. Працює для всіх поплавків.

repl.it


Пітон, 66 59 байт

-4 байти завдяки Lynn (використання -~)
-3 байти завдяки FlipTack (використання andта or, що дозволяють ...==1перейти на ...-1стан.)

f=lambda n:sum(-~n%-~i<1for i in range(n))-1and f(n+1)or-~n

repl.it

Рекурсивна функція, яка відлічується від nмоменту, до того, як буде знайдено простим числом, перевіривши, що існує лише одне число до того, n-1яке ділить її (тобто 1). Працює для всіх цілих чисел, викликає помилку для поплавків.

Працює на 2.7.8 та 3.5.2, не працює на 3.3.3 (помилка синтаксису через брак місця між ==1і else)


(n+1)%(i+1)є -~n%-~i, я думаю.
— Лін

Це, дякую ... Я намагався зробити коротший, використовуючи теорему Вілсона.
— Джонатан Аллан

Чи працює коротке замикання and/ orпрацює, наприклад f=lambda n:sum(-~n%-~i<1for i in range(n))==1and-~n or f(n+1)?
— FlipTack

Насправді, що ^ можна пограти в f=lambda n:sum(-~n%-~i<1for i in range(n))-1and f(n+1)or-~n
— гольф

@FlipTack Я спочатку їх уникав, щоб він міг пройти через нуль, але він буде працювати - це збереження в три байти!
— Джонатан Аллан

2

Пітон, 114 83 байти

def g(b):
 while 1:
  b+=1
  for i in range(2,b):
   if b%i<1:break
  else:return b

Без вбудованих, якщо такі є.

-30, видаливши пробіл та -1, змінивши b%i==0наb%i<1


3
Наступний прем'єр не знайде, якщо ви покладете участь1
— FlipTack

Тепер передбачається, що b> 2
— sagiksp

Ви не можете просто скласти свої власні правила ... вам потрібно слідувати специфікації виклику. Ніде не сказано, що ви можете припустити межі введення.
— FlipTack

Навіть при такому припущенні це не вдається для всіх навіть оцінених даних.
— FlipTack

Я ідіот, я його неправильно прочитав. Виправлено це. @FlipTack
— sagiksp

2

Perl 6 , 25 байт

{first *.is-prime,$_^..*}

Як це працює

{                       }  # A lambda.
                  $_ ..*   # Range from the lambda argument to infinity,
                    ^      # not including the start point.
 first           ,         # Iterate the range and return the first number which
       *.is-prime          # is prime.

Perl 6 , 32 байти

{first {all $_ X%2..^$_},$_^..*}

За допомогою неефективного тестування примітивності.

Як це працює

Зовнішня структура така ж, як і вище, але предикат, переданий first(щоб вирішити, чи задане число є простим), зараз:

{               }  # A lambda.
     $_            # Lambda argument (number to be tested).
          2..^$_   # Range from 2 to the argument, excluding the end-point.
        X          # Cartesian product of the two,
         %         # with the modulo operator applied to each pair.
 all               # Return True if all the modulo results are truthy (i.e. non-0).

Я сподівався отримати щось коротше з Perl 5, але важко обіграти вбудований .is-prime;)
— Zaid

2

Пайк, 8 7 байт

~p#Q>)h

Спробуйте тут!

4 байти, неконкурентоспроможні

(Перекладач оновлений з моменту опублікування виклику)

~p<h

Спробуйте тут!

~p   -   primes_iterator()
  <  -  filter(^, input() < i)
   h - ^[0]

Чому друге неконкурентоспроможне? Я недостатньо розумію.
— theonlygusti

@theonlygusti: Зазвичай, єдиною законною причиною відмітити подання, яке тут не конкурує (на відміну від його взагалі надсилання), є те, що ви виправили помилку або додали функцію мовою, якою написана програма, і це допомогло вам у вирішенні проблеми . (Я схильний писати це як "виклик мови після публікації", щоб бути більш зрозумілим.)

@theonlygusti уточнено
— Блакитний


1

05AB1E , 16 13 байт (Emigna @ -3 байт)

2•7£?ÿ•o[>Dp#

Спробуйте в Інтернеті!

2•7£?ÿ•o        # Push current largest prime.
        [   #    # Until true..
         >Dp    # Increment by 1, store, check primality.
                # After infinite loop, implicitly return next prime.

Не буде [>Dp#працювати?
— Емінья

Ви все ще можете вирізати ще 8 байт, оскільки програма повинна приймати простий вхід і виводити наступний прайм.
— Емінья

@Emigna, тоді це питання є дублікатом.
— Чарівний восьминога Урна

Це, ймовірно, так.
— Емінья

1

Perl, 30 байт (29 +1 для -p):

(1x++$_)=~/^(11+?)\1+$/&&redo

Використання

Введіть число після натискання return (введіть 12345 у прикладі нижче, виводи 12347):

$ perl -pe '(1x++$_)=~/^(11+?)\1+$/&&redo'
12345
12347

Як це працює

  • Визначте рядок 1s, який має довжину ++$_, де $_спочатку є вхідне значення
  • Регекс перевіряє, чи є рядок 1s простою довжиною (пояснено тут ).
  • Якщо довжина рядка не є простим, чек повторно оцінюється на наступне ціле число ( ++$_)
  • Якщо довжина рядка є простим, неявна whileпетля виходить і -pдрукує значення$_
  • Примітка: не потрібно обробляти крайовий корпус "1"довжиною 1, оскільки він ніколи не буде використовуватися для значень, менших 1за специфікацію.

1

Java 7, 373 343 334 303 268 байт

import java.math.*;class M{public static void main(String[]a){BigInteger n,i,o,r=new BigInteger(a[0]);for(r=r.add(o=r.ONE);;r=r.add(o)){for(n=r,i=o.add(o);i.compareTo(n)<0;n=n.mod(i).compareTo(o)<0?r.ZERO:n,i=i.add(o));if(n.compareTo(o)>0)break;}System.out.print(r);}}

-75 байт дякую @Poke

Безголівки:

import java.math.*;
class M{
  public static void main(String[] a){
    BigInteger n,
               i,
               o,
               r = new BigInteger(a[0]);
    for(r = r.add(o = r.ONE); ; r = r.add(o)){
      for(n = r, i = o.add(o); i.compareTo(n) < 0; n = n.mod(i).compareTo(o)< 0
                                                        ? r.ZERO
                                                        : n,
                                                   i = i.add(o));
      if(n.compareTo(o) > 0){
        break;
      }
    }
    System.out.print(r);
  }
}

Спробуйте тут.

Деякі приклади входів / виходів:

7 -> 11
1609 -> 1613
104723 -> 104729

@Poke Я пограв ще 31 байт, додавши staticдля поля та методу p, але видаливши метод cта pпараметр 's.
— Kevin Cruijssen

0

QBIC , 34 байти

:{a=a+1[2,a/2|~a%b=0|b=a]]~a<b|_Xa

На основі цього тестеру первинності QBIC . Пояснення:

:{a=a+1    Read 'a' from the command line, start an infinite loop 
           and at the start of each iteration increment 'a'
[2,a/2|    FOR b = 2, b <= a/2, b++
~a%b=0|    IF b cleanly divides a, we're no prime
b=a]]      so, break out of the FOR loop ( ]] = End if, NEXT )
~a<b|      If the FOR loop completed without breaking
_Xa        then quit, printing the currently tested (prime) number
           The second IF and the DO-loop are implicitly closed by QBIC.

0

JavaScript (ES7), 61 байт

a=>{for(;a++;){for(c=0,b=2;b<a;b++)a%b||c++;if(!c)return a;}}

Використання

f=a=>{for(;a++;){for(c=0,b=2;b<a;b++)a%b||c++;if(!c)return a;}}
f(2)

Вихідні дані

3

Приємно, але я не думаю, що це спрацює, оскільки сам JavaScript (не комп'ютер) втратить точність лише через 2 ^ 53.
— ETHproductions

Ви маєте рацію, але я не думаю, що цього обмеження неможливо уникнути, навіть якщо ми розділимо кількість на 32-бітні частини в масиві, тому що зрештою, число потрібно обробляти в цілому. Якщо у вас є ідея щодо вирішення цього питання, будь ласка, дайте мені знати.
— Лука

1
Є бібліотеки JS для математики з довільною точністю - я навіть побудував її в якийсь момент - тому я впевнений, що це можливо. Я буду їхати наступного разу, коли я за своїм комп’ютером
— ETHproductions

Я зробив якийсь гуглінг, і це здається цікавим. Я теж постріляю.
— Лука

0

MATL, 3 байти

_Yq 

Функція Yq повертає наступне просте абсолютне значення вхідного сигналу, якщо вхід негативний, тому ми неявно захоплюємо вхід, заперечуємо його ( _) і знаходимо наступне просте використання Yq.

Спробуйте в Інтернеті!


0

Хаскелл, 42 46 43 байт

f n=[i|i<-[n..],all((>0).rem i)[2..i-1]]!!1

звичайний код для грубої сили.

Звичайно, це знаходить наступне найменше просте число післяn . Немає найбільшого розквіту.

Працює при n > 0 .

редагувати: припускає, що nце головне. Завдяки поради @Laikoni в коментарях .


Ви можете зберегти байт, замінивши head[...]на [...]!!0. Однак я думаю, що можна припустити, що nце просто, тому можна використовувати [n..]замість, [n+1..]а потім взяти другий елемент [...]!!1.
— Laikoni

0

SimpleTemplate, 132 байти

Алгоритм жахливий, оскільки я маю робити власний код, щоб перевірити, чи є число простим чи ні.
Це виявилося жахливо, але працює.

{@setY argv.0}{@setX 1}{@whileX}{@setX}{@set+T Y,-1}{@for_ from2 toT}{@ifY is multiple_}{@incX}{@/}{@/}{@ifX}{@incY}{@/}{@/}{@echoY}

Отримує число в якості першого аргументу, виводячи результат.


Безголівки:

{@set number argv.0}
{@set remainder 1}
{@while remainder}
    {@set remainder 0}
    {@set+ tmp number, -1}
    {@for divisor from 2 to tmp}
        {@if number is multiple divisor}
            {@inc by 1 remainder}
        {@/}
    {@/}
    {@if remainder}
        {@inc by 1 number}
    {@/}
{@/}
{@echo number}

Будь-які поради щодо видалення останнього @if?


0

Луа, 876 байт

function I(a)a.s=a.s:gsub("(%d)(9*)$",function(n,k)return tostring(tonumber(n)+1)..("0"):rep(#k)end)end function D(a)a.s=a.s:gsub("(%d)(0*)$",function(n,k)return tostring(tonumber(n)-1)..("9"):rep(#k)end):gsub("^0+(%d)","%1")end function m(a,b)local A=K(a)local B=K(b)while V(0,B)do D(A)D(B)end return A end function M(a,b)local A=K(a)local B=K(b)while V(m(B,1),A)do A=m(A,B)end return A end function l(n)return#n.s end function p(a)local A=K(a)local i=K(2)while V(i,A)do if V(M(A,i),1)then return false end I(i)end return true end function V(b,a)A=K(a)B=K(b)if l(A)>l(B)then return true end if l(B)>l(A)then return false end for i=1,l(A)do c=A.s:sub(i,i)j=B.s:sub(i,i)if c>j then return true elseif c<j then return false end end return false end function K(n)if(type(n)=='table')then return{s=n.s}end return{s=tostring(n)}end P=K(io.read("*n"))repeat I(P)until p(P)print(P.s)

Lua, на відміну від деяких інших мов, має максимальний цілий розмір. Як тільки число стає більшим за 2 32 , речі перестають працювати правильно, і Луа починає намагатися робити оцінки замість точних значень.

Як такий, мені довелося реалізувати новий метод зберігання чисел, зокрема, я зберігав їх як рядки Base10, оскільки Lua не має обмеження розміру на Strings, окрім розміру пам'яті.

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

Пояснив

-- String Math
_num = {}

_num.__index = _num

-- Increase a by one.
-- This works by grabbing ([0-9])999...$ from the string.
-- Then, increases the first digit in that match, and changes all the nines to zero.
-- "13", only the "3" is matched, and it increases to 1.
-- "19", firstly the 1 is turned to a 2, and then the 9 is changed to a 0.
-- "9" however, the 9 is the last digit matched, so it changes to "10"
function _num.inc(a)
    a.str = a.str:gsub("(%d)(9*)$",function(num,nines)
            return tostring(tonumber(num)+1)..("0"):rep(#nines)
        end)
end


-- Decrease a by one
-- Much like inc, however, uses ([0-9])0...$ instead.
-- Decrements ([0-9]) by one and sets 0... to 9...
-- "13" only the "3" is matched, and it decreases by one.
-- "10", the "1" is matched by the ([0-9]), and the 0 is matched by the 0..., which gives 09, which is clipped to 9.
function _num.dec(a)
    a.str = a.str:gsub("(%d)(0*)$",function(num,zeros)
        return tostring(tonumber(num)-1)..("9"):rep(#zeros)
    end)         :gsub("^0+(%d)","%1")
end

-- Adds a and b
-- Makes A and B, so that the original values aren't modified.
-- B is then decremented until it hits 0, and A is incremented.
-- A is then returned.
function _num.__add(a,b)
    local A = str_num(a)
    local B = str_num(b)
    while B > 0 do
        A:inc()
        B:dec()
    end
    return A
end

-- Subs b from a
-- Works just like Addition, yet Dec's A instead of Incs.
function _num.__sub(a,b)
    local A = str_num(a)
    local B = str_num(b)
    while B > 0 do
        A:dec()
        B:dec()
    end
    return A
end

-- A % B
-- Makes A and B from a and b
-- Constantly subtracts B from A until A is less than B
function _num.__mod(a,b)
    local A = str_num(a)
    local B = str_num(b)
    while A >= B do
        A = A - B
    end
    return A
end

-- #a
-- Useful for golfiness
function _num.__len(n)
    return #n.str
end

-- Primacy Testing
-- Generates A from a and i from 2.
-- Whilst i is less than A, i is incremented by one, and if A % i == 0, then it's not a prime, and we return false.
-- Once that finishes, we return true.
function _num.isprime(a)
    local A = str_num(a)
    local i = str_num(2)
    while i < A do
        if A%i < 1 then
            return false
        end
        i:inc()
    end
    return true
end

-- b < a
-- A and B are generated from a and b
-- Fristly, if the length of A and B aren't equal, then that result is output.
-- Otherwise, each character is searched from left to right, the moment they are unequal, the difference is output.
-- If all the characters match, then it's equal. Return false.
function _num.__lt(b,a)
    A=str_num(a)
    B=str_num(b)
    if #A > #B then
        return true
    end
    if #B > #A then
        return false
    end
    for i=1, #A.str do
        As = A.str:sub(i,i)
        Bs = B.str:sub(i,i)
        if As > Bs then
            return true
        elseif As < Bs then
            return false
        end
    end
    return false
end


-- b <= a
-- Same as b < a, but returns true on equality.
function _num.__le(b,a)
    A=str_num(a)
    B=str_num(b)
    if #A > #B then
        return true
    end
    if #B > #A then
        return false
    end
    for i=1, #A.str do
        As = A.str:sub(i,i)
        Bs = B.str:sub(i,i)
        if As > Bs then
            return true
        elseif As < Bs then
            return false
        end
    end
    return true
end

-- Just straight up returns it's string component. Endlessly faster than the int equivalent, mostly because it never is anything _but_ the string form.
function _num.__tostring(a)
    return a.str
end

-- Just set up the metatable...
function str_num(n)
    if(type(n)=='table')then
        return setmetatable({str = n.str}, _num)
    end
    return setmetatable({str = tostring(n)}, _num)
end

-- Generate a new str_num from STDIN
Prime = str_num(io.read("*n"))

-- This is handy, because it will call Prime:inc() atleast once, and stop at the next prime number it finds.
-- Basically, if it weren't for all that overhead of making the math possible, that's all this would be.
repeat
    Prime:inc()
until Prime:isprime()
print(Prime)

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


0

Ruby, 28 + 6 = 34 байти

Використовує -rprimeпрапор.

f=->i{i+=1;i.prime??i :f[i]}

Нерекурсивна версія для 31 + 6 = 37 байт:

->i{i+=1;i+=1 while i.prime?;i}

0

Python + primefac , 34 32 байти

Не настільки короткий, як використання sympy(інша відповідь вже використовує це), але він все ще досить короткий, і він набагато швидший.

import primefac as p
p.nextprime

Спробуйте в Інтернеті

Введення 2**2000завершується через пару секунд.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.