该程序将找到下一个素数


15

介绍:


您不小心用了一个有趣的设备破坏了时间流,该设备原来是一台时间机器。结果,您被推到了遥远的未来。您意识到计算,处理能力和计算机总体上已经发生了巨大的发展,确切地说,它是无限的。因此,您可以抢购一台具有无限内存和处理能力的计算机。您不知道它如何具有无限的内存和无限的处理能力,但是您只接受它并回到现在。

挑战:


您听说发现当前最大黄金的人2^74,207,281 − 1获得了$ 100.000的报酬。您决定制作一个程序来查找下一个素数,因为您想取回在计算机上花费的钱。您可以制作一个通过输入数字并通过暴力破解或任何其他方法找到下一个质数的数字。

说明: 您有一台假设的机器,具有无限的存储和处理能力。您的程序一定不能受到限制(例如:C#的int可以存储从-2,147,483,6482,147,483,647),那么您的程序必须能够存储并且可以使用任意数量的任何大小的文件。您拥有无限的资源,因此如果允许,则不必担心是否会耗尽内存。

I / O示例:
输入:当前发现的最大质数,具有22,338,618位数字。
输出:正好是下一个素数

显然,您不必证明它可以工作,因为在物理机上进行计算将花费大量时间。但是,如果将程序转移到具有无限处理能力/内存的虚拟机上,它应该立即进行计算。


找到下一个质数并检查数字是否为质数是两件完全不同的事情


1
是否一定要成为下一个素数?许多针对大素数的素数搜索算法只能搜索某些类型的数字,因此有时会漏掉素数...
FlipTack

10
我认为您应该添加一些严肃的测试用例。
FlipTack

3
您的程序一定不能受到限制 ”,但是基于该示例,我怀疑存在的每一种语言,除了使用有限类型来寻址内存外,如果没有其他原因也算为有限。
彼得·泰勒


2
@ mbomb007为什么?除内置答案外,所有答案仅添加一个额外的包装。
发布Rock Garf Hunter,

Answers:



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 mod k,乘以k便是k本身。您可以计算平方来消除(k-1)的唯一例外!= 0 mod k对于复合k,在k = 4时会发生。
orlp

对,那是正确的。
丹尼斯,

这引发RecursionError: maximum recursion depth exceeded in comparisonf(1000)
OVS

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<1n%i==0
-Kritixi Lithos

之后,您不需要空格if
FlipTack

我认为您的意思是<1
乔纳森·艾伦

我认为您可以为第二级缩进使用制表符而不是2个空格,但目前无法测试。
ElPedro

1
@ElPedro是正确的。你可以改变在前面的2个空格n+=1,并if为标签和节省2个字节



4

Bash + coreutils,52个字节

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

在线尝试!

bash和factor的文档未指定它们可以处理的最大整数值(尽管实际上,每个实现都具有最大整数值)。据推测,在未来的GNU无限大型计算机上,bash和factor将具有无限大小的整数。


实际上,文档确实指定了因素,如果在不使用gnu mp的情况下构建,则仅支持单精度。
Dani_l

1
@Dani_l好吧,bash的man条目只说:“评估是用固定宽度的整数完成的,没有检查溢出的情况,尽管陷阱除以0并标记为错误。” 它没有指定宽度。(我记得,我机器上bash的常规实现使用64位有符号整数,但现在无法检查。)至于因素,它肯定会更新:OP拥有无限资源的未来计算机将具有因素用gnu_up编译以获得无限的精度:)。
米切尔·斯佩克托

3

最大值,10个字节

next_prime

函数返回的最小质数大于其参数。



3

带有sympy的Python,28个字节

import sympy
sympy.nextprime

sympy.nextprime是一个功能,它会在锡上说出它的意思。适用于所有浮子。

代表


Python,66 59字节

感谢Lynn(使用-~)-4字节,感谢
FlipTack -3字节(使用andor,允许...==1切换到...-1条件。)

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

代表

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

@FlipTack我本来是避免使用它们的,所以它可以通过零,但是它可以工作-节省了三个字节!
乔纳森·艾伦

2

Python,114 83字节

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

没有内置函数,如果有的话。

删除空格,则返回-30,更改b%i==0为则返回-1b%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

Pyke,8个 7字节

~p#Q>)h

在这里尝试!

4字节,无竞争

(自发布挑战以来,口译员已更新)

~p<h

在这里尝试!

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

为什么第二个不竞争?我不太了解。
theonlygusti

@theonlygusti:通常,在此处将提交标记为不竞争(而不是完全不提交)的唯一合理原因是,您修复了错误或以程序编写的语言添加了功能,从而帮助您应对了挑战。(我更倾向于将其写为“语言发布日期挑战”,以使其更加清晰。)

@theonlygusti进行了澄清
蓝色


1

05AB1E16 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#
Emigna

您仍然可以再减少8个字节,因为程序应以素数作为输入并输出下一个素数。
Emigna '17

@Emigna然后这个问题是重复的。
魔术章鱼缸

那可能是的。
Emigna

1

Perl,30个字节(对于,为29 +1 -p):

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

用法

在按回车键后输入数字(以下示例中输入12345,输出12347):

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

怎么运行的

  • 定义一个1长度为的的字符串++$_,其中$_最初是输入值
  • 正则表达式检查以查看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通过添加static字段和方法p,我又打了31个字节,但删除了方法cp的参数。
凯文·克鲁伊森'17

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'Jan

我做了一些谷歌搜索,这看起来很有趣。我也会对此进行尝试。
路加福音

0

MATL,3个字节

_Yq 

Yq如果输入为负,函数将返回输入绝对值的下一个素数,因此我们隐式抓取输入,对其_求反(),并使用查找下一个素数Yq

在线尝试!


0

Haskell,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 '17

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

Lua,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,事情就会停止正常工作,Lua开始尝试估算而不是精确值。

因此,我必须实现一种存储数字的新方法,特别是,我将它们存储为Base10字符串,因为Lua除了内存的大小外,对字符串没有大小限制。

我觉得这个答案对问题的精神更重要,因为它必须实现任意精度的整数,以及一个素数测试。

解释

-- 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 + primefac34 32字节

不是很短的使用sympy(另一种答案已经使用了),但它仍然很短,这是很多更快。

import primefac as p
p.nextprime

在线尝试

2**2000几秒钟内完成输入。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.