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


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.