在不使用“素数字符”的情况下查找素数


21

您的任务(如果选择接受)是编写一个接受整数N作为输入的程序/函数。程序/功能应输出/返回前N个质数的列表。但是这里有个要点:不允许在代码中使用质数字符。素数字符是指其Unicode代码点是素数的字符。在可打印的ASCII范围内,这些是:

%)+/5;=CGIOSYaegkmq

但是,如果您的代码使用非ASCII字符,则该规则也适用于非ASCII字符。

  • 有效的输入是一个整数Ñ其中0 <N <= T,其中,可以选择Ť,但它必须大于或等于10000。Ť不必是有限的。
  • 对于无效输入(非整数,超出范围的整数),抛出异常或输出/不返回任何结果/为空。
  • 以前导/结尾空白为输入的整数被认为是无效的。
  • +以符号字符作为输入的整数被视为无效。
  • 以前导零作为输入的整数被视为有效。
  • 如果您的语言允许您传递已经解析的整数作为输入,则上述解析规则(范围1除外)将不适用,因为int已被解析。
  • 输入始终为10。
  • 不允许使用内置的素数生成器和素数测试器(包括素数分解函数)。
  • 源限制是对Unicode字符强加的,但是如果需要,可以对分数的字节计数进行其他编码。
  • 输出可以包含单个尾随换行符,但这不是必需的。
  • 如果您以字符串形式输出/返回素数列表,则每个素数必须由一个或多个非数字字符定界。您可以选择使用哪个定界符。
  • 这是一个挑战,最短的代码以字节为单位获胜。

堆栈代码片段以验证您的代码

您可以使用下面的堆栈片段来验证您的代码不包含素字符:

var primes=[],max=10000;for(var i=2;i<=max;i++){primes.push(i);}for(var N=2;N<Math.sqrt(max);N++){if(primes.indexOf(N)===-1){continue;}primes=primes.filter(function (x){return x===N||x%N!==0;});}function setText(elem,text){var z=('innerText' in elem)? 'innerText' : 'textContent';elem[z]=text;}function verify(inputCode,resultSpan){var invalidChars=[];var success=true;for(var i=0;i<inputCode.length;i++){var cc = inputCode.charCodeAt(i);if (cc>max){setText(resultSpan,"Uh oh! The char code was bigger than the max. prime number calculated by the snippet.");success = false;break;}if (primes.indexOf(cc)!==-1){invalidChars.push(inputCode[i]);}}if (invalidChars.length===0&&success){setText(resultSpan, "Valid code!");}else if(success) {  var uniqueInvalidChars = invalidChars.filter(function (x, i, self){return self.indexOf(x)===i;});setText(resultSpan, "Invalid code! Invalid chars: " + uniqueInvalidChars.join(""));    }}document.getElementById("verifyBtn").onclick=function(e){e=e||window.event;e.preventDefault();var code=document.getElementById("codeTxt").value;verify(code,document.getElementById("result"));};
Enter your code snippet here:<br /><textarea id="codeTxt" rows="5" cols="70"></textarea><br /><button id="verifyBtn">Verify</button><br /><span id="result"></span>


10
这是很残酷的是;恰巧被禁止...
ɐɔıʇǝɥʇuʎs

如果不允许使用素数测试器,那么素因数分解函数呢?
Maltysen

@Maltysen从素数分解函数中,您可以非常快速地查看数字是否为素数,因此恐怕是不允许的。我会澄清这一点。
ProgramFOX

我们是否被要求丢弃其中一些无效输入?例如,如果我们语言的string-> int函数允许使用Leading +,那么手动将它们扔掉似乎令人失望。
Runer112

11
我对此感到非常兴奋,并开始寻找解决方案,然后才意识到封闭的括号是不允许的。好吧,我出去了。
Alex A.

Answers:


10

CJam,19 18 30 34 33 19 17 21 20字节

在线尝试。

{_3\#,2>__ff*:~-<N*}

这可能是我执行过的效率最高的算法之一。但是我做到了!

我的答案包括一个代码块,其作用类似于CJam中的匿名函数。在堆栈上紧随其后的整数前运行它,结果列表将转储到堆栈上。我将输入的上限视为无穷大,因此不必检查该上限。

我的算法首先将3乘以3的input幂,input如果输入有效,则保证给出一个大于-th素数的数字。然后生成一个从2到此数字减一的整数列表,该列表足够大,足以包含我们想要的所有素数。为了摆脱合成数... 叹息 ...我们创建每个成对乘积的列表,该列表将生成所有合成数,范围从4到某个非常大的值,足以满足我们的目的。然后,只需从该组合列表中的原始列表中删除每个元素,将其修剪到第一个input元素,然后将这些元素与换行符相连即可。

该算法适用于任何输入。但是,解释器/计算机是否具有足够的内存或时间是另一个完全的问题,因为时间和空间要求相对于输入是指数的。因此,如果在线解释器的输入大于大约5或离线解释器的输入大约大于8,那么该问题的答案可能是“否”。


3
嘿,在17岁时,答案中有一个素数字节。
科里·奥格本

为什么需要一个S*
jimmy23013 2015年

@ user23013小于1的无效输入仍会通过算法传递,它们只会产生一个空列表。但这对他们来说不是合法的输出,因此我将list元素与空格连接起来,以为这些无效输入生成空输出。
2015年

1
我注意到了,这不是S素字吗?
扎卡里

这是一个主要人物。我知道我是2年以上下旬说,但这个答案应该是无效的
扎卡里

8

Java。474字节

i\u006dport j\u0061v\u0061.util.*\u003bvoid b(int b\u0029{Lon\u0067 c\u003d2L,d,f[]\u003d{}\u003bfor(f\u003dArr\u0061ys.copy\u004ff(f,b\u0029,Arr\u0061ys.fill(f,0L\u0029\u003bb-->0\u003b\u0029for(d\u003d0L\u003bf[b]<1\u003bf[b]\u003dd<1?c:f[b],d\u003d0L,c\u002b\u002b\u0029for(lon\u0067 h:f\u0029d\u003dh>0&&c\u002fh*h\u003d\u003dc?1:d\u003bj\u0061v\u0061x.x\u006dl.bind.JAXB.un\u006d\u0061rsh\u0061l(""\u002bArr\u0061ys.\u0061sList(f\u0029,Lon\u0067.cl\u0061ss\u0029\u003b}

通过函数参数获取输入,通过抛出异常输出。

缩进:

i\u006dport j\u0061v\u0061.util.*\u003b
void b(int b\u0029{
    Lon\u0067 c\u003d2L,d,f[]\u003d{}\u003b
    for(f\u003dArr\u0061ys.copy\u004ff(f,b\u0029,Arr\u0061ys.fill(f,0L\u0029\u003bb-->0\u003b\u0029
        for(d\u003d0L\u003bf[b]<1\u003bf[b]\u003dd<1?c:f[b],d\u003d0L,c\u002b\u002b\u0029
            for(lon\u0067 h:f\u0029
                d\u003dh>0&&c\u002fh*h\u003d\u003dc?1:d\u003b
    j\u0061v\u0061x.x\u006dl.bind.JAXB.un\u006d\u0061rsh\u0061l(""\u002bArr\u0061ys.\u0061sList(f\u0029,Lon\u0067.cl\u0061ss\u0029\u003b
}

转义字符已删除:

import java.util.*;
void b(int b){
    Long c=2L,d,f[]={};
    for(f=Arrays.copyOf(f,b),Arrays.fill(f,0L);b-->0;)
        for(d=0L;f[b]<1;f[b]=d<1?c:0,d=0L,c++)
            for(long h:f)
                d=h>0&&c/h*h==c?1:d;
    javax.xml.bind.JAXB.unmarshal(""+Arrays.asList(f),Long.class);
}

说明:

Long c,d,f[]={};                                                //Initialize variables.

for(f=java.util.Arrays.copyOf(f,b),Arrays.fill(f,0L);b-->0;)
    f=java.util.Arrays.copyOf(f,b),Arrays.fill(f,0L)            //Initialize f to an array of 0's.
                                                     b-->0      //Iterate over the first b primes.

for(d=0L;f[b]<1;f[b]=d<1?c:0,d=0L,c++)
    d=0L                        d=0L                            //Initialize d to 0.
         f[b]<1                      c++                        //Increment c while the b'th prime is 0.
                f[b]=d<1?c:0                                    //If d = 0, the b'th prime = c, else continue.

for(long h:f)                                                   //Iterate over all found primes.

d=h>0&&c/h*h==c?1:d;
  h>0                                                           //Ignore non-found primes.
       c/h*h==c                                                 //Equivalent to c%h==0
               ?1:d                                             //If h is prime and c is divisible by h, d = 1. Otherwise d stays unchanged.

javax.xml.bind.JAXB.unmarshal(""+Arrays.asList(f),Long.class)   //Print solution to stderr
javax.xml.bind.JAXB.unmarshal(                   ,Long.class)   //Prints what's contained to stderr.
                                 Arrays.asList(f)               //Convert f to list.
                              ""+                               //Convert to string.

我最初的解决方案使用了一个return声明。在StackOverflow上问了这个问题之后,regettman很友善地提供了一种无需使用素数字母即可输出/返回的方法。

和往常一样,欢迎提出建议:)


3
+1。对于您和rgettman来说,这确实非常困难。非常令人印象深刻。:)
TNT

5

Ruby,74岁

->n,*o{o<<[2..n*n][0].find{|x|!o.find{|y|1.>x.^y.*x.div y}}until o[n-1]
o}

说明:

*o初始化一个空的输出数组。直到n找到项目为止,我们找到最小的数字> = 2,该数字不除当前中的任何项目o,然后将其添加到中o。为了测试分裂,是的。所有好的运算符都被禁止,我什至不能使用divmod。我所能看到的最好是使用x.div y,将x除以y并四舍五入,然后再乘以y。如果等于x,则不进行舍入,因此y将x除。1.>x.^是一个相等性测试,检查xor的结果是否为0。.每个运算符之前的原因是因为您无法混用.-free运算符调用和无括号的方法调用。

编辑:我认为在我发布此内容后添加了范围检查规范。要遵守,需要79个字符:

->n,*o{o<<[*2..-~n*n].find{|x|!o.find{|y|1.>x.^y.*x.div y}}until o[n-1]||n<1
o}

4

CJam,38 37 30字节

{_~2#,2>\{(\{1$37c~},\p}*'<(~}

在这里尝试

我认为这应符合所有规则,并且适用于任何非负N(即T为无穷大)。但是,它效率极低,所以不要大量尝试。

这是一个块-最接近(未命名)函数的块-该块期望堆栈上有一个整数,打印所有质数,并使堆栈没有输入。对于所有无效输入,它将抛出错误或不打印任何内容。

大部分代码是输入验证,然后是Eratosthenes筛。我只需要在3个地方解决输入限制:

  • )是CJam中的增量。我只需要一次,但是可以用~(按位补码)替换它,因为无论如何我以后都要对数字求平方。
  • %是模。我正在使用37c~,它首先创建角色%,然后评估。这使代码变慢了很多。
  • ;从堆栈中弹出并丢弃一个元素。最后我需要这样做。取而代之的是,我使用'<(~它来推动字符<,减少字符并进行评估。

我认为,鉴于所有输入的解析规则,我们不允许只接受一个已经解析的整数。
2015年

@ Runer112我们被允许编写“接受整数的函数”。不是“接受整数的字符串表示形式的函数”。
马丁·恩德

3

Bash + coreutils,227字节

printf -vb br`dc<<<Di14B8209P`
printf -vc -- $[$1-0]
[ "${1#$c}" -o $c -lt 1 ]||{
for i in {2..104729}
{
for f in `jot $[i-1] $[i-1] 1`
{
[ 0 -lt `dc<<<"$i $f~p"` ]||$b
}
[ $f -lt 2 ]&&printf $i\ &&: $[c--]
[ $c -lt 1 ]&&$b
}
}

这很棘手。我遇到了一些问题:

  • 大多数循环(whileuntil)不可用,因为它们最接近的done是shell关键字,并且不能是变量扩展的结果(除非eval使用了,但也没有用)。唯一可用的循环是for/ in,它允许{/ }代替do/ donefor (( ; ; ))也无法使用。
  • =出来了,所以我们需要另一种分配变量的方法。 printf -v对此有好处。
  • 我们知道p(10000)是104729,所以对于潜在质数的外循环,我们可以简单地从2循环到104729,一旦我们有足够的质数就中断
  • jot生成内循环中的潜在因素列表。如果潜在因素除以潜在的素数,那么它不是素数,我们会尽早爆发
  • 幸运的break是,它是内置的Shell而不是关键字,因此可能是扩展产生的。 dc将基数13转换为字节流eak
  • 要检查潜在因子是否除以潜在素数,我们不能使用常规运算符/%shell算术运算符。因此,这被外包给dcs ~运算符,后者将商和余数压入堆栈。
  • -lt -小于-是唯一可用的shell比较运算符。
  • echo对输出无用。 printf只要我们避免就可以%

正确进行输入验证有点麻烦。如果输入无效,则不返回任何内容。

输出:

$ ./primenoprime.sh 10
2 3 5 7 11 13 17 19 23 29 $ 

3

Haskell,90个字节

\n->[fst c|c<-zip[p|p<-[2..],not$or[b>p-1&&b-1<p|b<-[u*v|u<-[2..p-1],v<-[2..p-1]]]][1..n]]

这是一个匿名函数,它以整数n作为输入。

工作原理:[p|p<-[2..],not$or[b>p-1&&b-1<p|b<-[u*v|u<-[2..p-1],v<-[2..p-1]]]]Haskell Wiki上素数单线的第一个示例,但替换了elem函数)创建了一个无限的素数列表。zip用从1到的数字n制作(prime, seq. number)成对的列表。删除序列。再次。结果是长度的素数的列表n


1

Rust,64897字节

|n|println!{"{:?}",&[2,3,6-1,7,11,13,17,19,23,29,31,37,41,43,47,60-7,0x3b,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,0x97,0x9d,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,0xfb,0x101 ...}

(由于字符数限制,代码被截断,此处提供完整解决方案

由于主要限制,以下防锈功能不可用:

  • 函数调用,因为它们需要')'
  • 常规绑定,因为它们需要让(e)
  • 宏定义,它们需要宏规则!(a,e,m)
  • 匹配语句,它们需要匹配(a,m)和=>(=)
  • 可变性,因为它总是与mut关键字(m)一起引入的。
  • 返回(e),中断(a,e),继续(e)
  • 其他(e)

技术上可以使用的是:

  • 如果。但除此之外,它们在表达式上下文中没有用,因此仅对副作用有利。
  • 宏。标准宏,例如打印!通常后跟(),但实际上使用{}或[]代替是合法的。没有这个,任务将是不可能的。
  • 从最狭义的意义上讲,闭包。您不能调用它们(需要())或绑定它们(需要let),但是可以定义一个非递归的对象。没有这个,任务显然将变得不可能。
  • 结构。
  • 循环。这些是有前途的,因为它们实际上允许变量绑定,并且采用了迭代器,该迭代器仍可以使用范围语法定义。迭代器甚至可以是表达式。
  • 内置运算符,+,%和/除外。逻辑运算符短路似乎很有希望。

我根本无法使用这些工具完成任何图灵完善的工作。对不起。剩下的只包括全部的前10000个素数,清除了5个素数。至少您可以对其进行切片,并在尽可能最窄的范围内找到有效的解决方案。

我非常希望图灵tarpit潜水(或Rust!)方面的专家告诉我是否可以做得更好!


1

GNU APL,75 68 67 65 59 56 55个字符

⎕IO必须是1

∇z←p n
z←2,j←3
j←j--2
→2×⍳∨⌿1>z|j
z←z,j
→2×⍳n>⍴z
z←n↑z∇

几个月后,我又回来了,意识到我还有多余的空间!


这是APL编码还是UTF-8?如果将其转换为APL编码(并且有效),则字节数会短得多。
NoOneIsHere

UTF-8。是的,但是在那些低俗的角色上,会有更多的素数。
扎卡里

确切地说,它现在已在APL中计算为字节,但对源的限制是Unicode。(我意识到挑战允许非Unicode字节数)
扎卡里

0

Pyth -12个字节

使用pyth的素数分解函数查看#是否为素数。!tPT在回答百万以下质数问题时,向我建议了使用技巧。

<f!tPTr2^T6Q

由于该过滤器仅适用于n以下的素数,而不适用于前n的素数,因此我只对pi(x)的反函数求10,000,得到104,000,所以我使用10⁶以下的素数得到前n。它实际上并没有运行,因此您应该通过替换^T6^T3n并将n限制为1000以下进行测试。

<          Q     Slice first n
f     r2^T6      filter on range 2->10⁶
 !               Logical not (gives true if tail is empty)
  t              Tail (all but first, so gives empty if prime fact is len 1)
   PT            Prime factorization of filter var (len 1 if num is prime)

5
根据规则:“不允许使用内置的素数生成器和素数测试器。”
Runer112

@ Runer112是的,但这不是素数测试器,素数分解是规则的边界。我可能应该问是否允许这样做。
Maltysen

@Maltysen 不允许使用内置的素数生成器和素数测试器(包括素数分解函数)” -对我来说似乎很清楚。
Digital Trauma 2015年

4
在发布此答案后,添加了@DigitalTrauma澄清“(包括素数分解函数)”。
马丁·恩德

MartinBüttner是的。我想这取决于@ProgramFOX的判断。
Digital Trauma 2015年
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.