这个数字是素数吗?


195

信不信由你,对于简单的素数测试,我们还没有针对高尔夫的代码挑战。尽管这可能不是最有趣的挑战,尤其是对于“常用”语言而言,但在许多语言中它可能并不平凡。

Rosetta代码按惯用方法的语言列出了用于素数测试的功能,一种方法专门使用Miller-Rabin测试,另一种方法使用试验部门。但是,“最惯用的”通常与“最短的”不重合。为了使“编程难题”和“代码高尔夫”成为代码高尔夫的首选站点,此挑战旨在汇编一种每种语言中最短方法的目录,类似于“ Hello,World!”。高尔夫球给你一个伟大的机会!

此外,实现素数测试的能力是我们对编程语言的定义的一部分,因此,这一挑战也将成为经过验证的编程语言的目录。

任务

编写一个完整的程序,给定严格的正整数n作为输入,该程序确定n是质数,并相应地打印真实或虚假值

出于此挑战的目的,如果整数恰好具有两个严格的正除数,则它是质数。请注意,这不包括1,后者是其唯一的严格除数。

您的算法必须是确定性的(即以概率1产生正确的输出),并且从理论上讲应该适用于任意大的整数。实际上,您可以假设输入可以存储在您的数据类型中,只要程序可以处理1到255之间的整数即可。

输入项

  • 如果您的语言能够从STDIN中读取,接受命令行参数或用户输入的任何其他替代形式,则可以读取整数作为其十进制表示形式,一元表示形式(使用您选择的字符),字节数组(大或小尾数)或单字节(如果这是您的语言所用的最大数据类型)。

  • 如果(且仅)您的语言无法接受任何类型的用户输入,则可以在程序中对输入进行硬编码。

    在这种情况下,硬编码整数必须易于交换。特别是,它可能仅出现在整个程序的单个位置。

    出于评分目的,提交与输入1对应的程序。

输出量

输出必须写入STDOUT或最接近的替代方案。

如果可能,输出应仅包含一个真值或假值(或其字符串表示形式),并可选地跟一个换行符。

该规则的唯一例外是您的语言解释器不断输出的内容,例如问候语,ANSI颜色代码或缩进​​,这些输出不能被禁止。

附加规则

  • 这并不是要找到用于最短时间测试的最短语言,而是要找到每种语言中最短的方法。因此,没有答案将被标记为已接受。

  • 大多数语言的提交都将以适当的预先存在的编码(通常(但不一定)为UTF-8)以字节计分。

    例如,Piet语言将在编码中得分,这是该语言的自然选择。

    某些语言(例如Folders)很难评分。如有疑问,请在Meta上提问。

  • 与我们通常的规则不同,即使使用的语言(或语言版本)比此挑战新,也可以使用。如果有人想通过创建一种在空程序执行素性测试的语言中滥用它的方法,那么祝贺您为一个非常无聊的答案铺平了道路。

    请注意,必须有一个解释器,以便可以测试提交。允许(甚至鼓励)自己为以前未实现的语言编写此解释器。

  • 如果您选择的语言是已经有答案的另一种(可能是更流行的)语言的琐碎变体(请考虑使用BASIC或SQL方言,Unix shell或琐碎的Brainfuck派生词,例如Headsecks或Unary),请考虑在现有答案中添加注释在其他语言中,相同或非常相似的解决方案也是最短的。

  • 测试素性内置功能允许的。这项挑战旨在将每种语言的最短解决方案归类,因此,如果使用您的语言的内置版本更短,那就去吧。

  • 除非之前已否决它们,否则所有标准的规则都适用,包括http://meta.codegolf.stackexchange.com/q/1061

附带说明一下,请不要在无聊的语言中打扰无聊(但有效)的答案;这些对于这个问题仍然很有用,因为它试图编译尽可能完整的目录。但是,主要是用作者实际上不得不努力打出代码的语言来提高答案的准确性。

目录

这篇文章底部的Stack Snippet会根据答案a)生成目录,a)作为每种语言的最短解决方案列表,b)作为整体排行榜。

为确保您的答案显示出来,请使用以下Markdown模板以标题开头。

## Language Name, N bytes

N您提交的文件大小在哪里。如果您提高了分数,则可以通过打败旧分数保持标题。例如:

## Ruby, <s>104</s> <s>101</s> 96 bytes

如果要在标头中包含多个数字(例如,因为您的分数是两个文件的总和,或者您想单独列出解释器标志罚分),请确保实际分数是标头中的最后一个数字:

## Perl, 43 + 2 (-p flag) = 45 bytes

您还可以将语言名称设置为链接,然后该链接将显示在代码段中:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


我可以将输入作为负数吗,其中abs(input)是我要测试的数字?
斯坦·斯特鲁姆

不,输入是严格的正整数。
丹尼斯

1
@LyndonWhite旨在将其作为原始性测试的目录(例如“ Hello,World!”),因此似乎更倾向于使用统一的提交格式。我对此感到遗憾,这是两个决定之一,另一个决定只允许进行确定性素数测试。
丹尼斯

1
@Shaggy好像是个元问题。
丹尼斯

1
是的,这就是我的想法。看到这是您的挑战,我会让您兑现荣誉。
粗野的

Answers:


225

你好,世界!,13

hello, world!

83
你一样,只是创造这种语言,只是这个提交?;)
ETHproductions 2015年

41
@ETHproductions看起来最近一次提交是在10天之前。
Geobits 2015年

39
在链接到任何地方之前,我希望它的语言略好一些,但是这一挑战已经发布,我无法抗拒。
histocrat

31
我几乎可以说,挂在输入1上是正确的功能。
iamnotmaynard 2015年

21
最好的部分是该程序不仅是内置程序,每个字符在获得正确结果方面都扮演着自己的角色。
ETHproductions 2016年

157

六边形,29字节

.?'.).@@/'/.!.>+=(<.!)}($>(<%

该代码的可读版本为:

   . ? ' .
  ) . @ @ /
 ' / . ! . >
+ = ( < . ! )
 } ( $ > ( <
  % . . . .
   . . . .

说明:它测试是否存在从2到n-1的数字除以n。

初始化:

将n写入一个存储单元,将n-1写入另一存储单元:

   . ? ' .
  . . . . .
 . . . . . .
+ = ( . . . .
 . . . . . .
  . . . . .
   . . . .

特殊情况n = 1:

打印0并终止

   . . . .
  . . . @ .
 . . . ! . .
. . . < . . .
 . . . . . .
  . . . . .
   . . . .

循环

计算n%a并减少a。如果a = 1或n%a = 0,则终止。

   . . . .
  ) . . . /
 ' / . . . >
. . . . . . .
 } ( $ > ( <
  % . . . .
   . . . .

情况a = 1:

将0增加到1,打印并终止。(指令指针在NE方向上运行,并从东角向西南角循环。并且$确保它忽略了下一个命令)

   . . . .
  . . . @ .
 . . . ! . .
. . . < . . )
 . . $ . . <
  . . . . .
   . . . .

情况a%n = 0:

打印0并终止(指令指针正在运行SW,并循环到@

   . . . .
  . . @ . .
 . . . . . >
. . . . . ! .
 . . . . . .
  . . . . .
   . . . .

61
天哪,这是一个令人印象深刻的第一篇文章。:)我现在会悬赏(我将在7天之内颁发奖金,以引起更多关注您的回答)。欢迎来到PPCG!
Martin Ender 2015年

35
好答案!1为“ 本代码的可读的版本是:<...> ” :-)
agtoever

68

六角形218 92 58 55字节

注意:该答案已被Etoplay的4边长解决方案强力击败。

)}?}.=(..]=}='.}.}~./%*..&.=&{.<......=|>(<..}!=...&@\[

第一个非平凡(即非线性)六角程序!它基于与Sp3000的迷宫答案相同的平方因子方法。从大小为10的六角形开始之后,我设法将其压缩为大小5。但是,我能够重用一些重复的代码,并且代码中仍然有很多无操作,因此大小4可能只是可能的。

说明

为了理解代码,我们首先需要将其展开。Hexagony使用no-ops将任何源代码填充到下一个居中的六边形数字(.61。然后,将代码重新排列为相应大小的正六边形:

     ) } ? } .
    = ( . . ] =
   } = ' . } . }
  ~ . / % * . . &
 . = & { . < . . .
  . . . = | > ( <
   . . } ! = . .
    . & @ \ [ .
     . . . . .

交叉和重叠的执行路径以及多个指令指针(IP)颇受青睐。为了解释它是如何工作的,让我们首先来看一个没有版本的版本,在该版本中,控制流不会通过边缘,只使用一个IP,并且执行路径尽可能简单:

             . . . . . . . . . . . . .
            . . . . . . . . . . . . . .
           . . . . . . . . . . . . . . .
          . . . . . . . . . . @ . . . . .
         . . . . . . . . . . ! . . . . . .
        . . . . . . . . . . % . . . . . . .
       . . . . . . . . . . ' . . . . . . . .
      . . . . . . . . . . & . . . . . . . . .
     . . . . . . . . . . { . . . . . . . . . .
    . . . . . . . . . . * . . . . . . . . . . .
   . . . . . . . . . . = . . . . . . . . . . . .
  . . . . . . . . . . } . . . . . . . . . . . . .
 ) } ? } = & { < . . & . . . . . . . . . . . . . .
  . . . . . . . > ( < . . . . . . . . . . . . . .
   . . . . . . = . . } . . . . . . . . . . . . .
    . . . . . } . . . = . . . . . . . . . . . .
     . . . . | . . . . | . . . . . . . . . . .
      . . . . * . . . ) . . . . . . . . . . .
       . . . . = . . & . . . . . . . . . . .
        . . . . > } < . . . . . . . . . . .
         . . . . . . . . . . . . . . . . .
          . . . . . . . . . . . . . . . .
           . . . . . . . . . . . . . . .
            . . . . . . . . . . . . . .
             . . . . . . . . . . . . .

旁注:上面的代码从执行第一行开始,该行无操作。然后,当IP到达东北边缘时,它会绕到最左侧的角()),从此处开始实际的代码。

在开始之前,先介绍一下Hexagony的内存布局。有点像Brainfuck在类固醇上的胶带。实际上,它不是磁带,而是六边形网格本身(一个无限的网格),其中每个都有一个整数值,该值初始为0(与标准Brainfuck相对,这些值是带符号的任意精度整数)。对于此程序,我们将使用四个边缘:

在此处输入图片说明

我们将在边A上计算阶乘,在边C上对输入进行递减计数,并在边D上存储输入的另一个副本(用于模)。B用作计算的临时边。

内存指针(MP)从边A开始,指向北(这对于MP的移动很重要)。现在,这是代码的第一位:

)}?}=&{

)递增边缘1作为阶乘的基础。}使MP右转,即移至边缘C(指向东北)。在这里,我们使用读取输入为整数?。然后,我们采取另一种右转到边d}=反转MP,使其指向与C共享的顶点。&将值从C(输入)复制到D-从左侧复制该值,因为当前值是非正数(零)。最后,我们让MP退居左转向Ç{

接下来,<从技术上讲是一个分支,但我们知道当前值是正数,因此IP始终会向右转>。从侧面命中的分支充当镜像,使得IP再次水平移动向(,从而使C的值减小。

下一个分支,<真正的一个分支了。这就是我们从n-1向下循环到的方式1。当C中的当前值为正时,IP右转(执行循环)。一旦达到零,它就会向左转。

让我们看一下“ body”循环。和|是简单的镜像,><也再次用作镜像。这意味着实际的循环体可以归结为

}=)&}=*}=

}将MP移动到边缘B=反转其方向以面对顶点ABC)递增值:这仅与第一次迭代有关,其中B的值仍为零:我们要确保其为正数,以便下一条指令&复制正确的邻居,即A,即阶乘的当前值计算,为

}然后将MP移到A=再次将其反转以面对公用顶点。*将两个邻居(即边BC)相乘并将结果存储在A中。最后,我们还有另一个}=要返回到C的位置,仍然面对顶点ABC

我希望你能看到这是如何计算的阶乘n-1一个

因此,现在我们已经完成了,C中的循环计数器为零。我们要对阶乘进行平方,然后对输入取模。这就是这段代码的作用:

&}=*{&'%!@

由于C为零,因此&复制左邻居,即A中的阶乘。}=*移到B并将阶乘的两个副本(即正方形)的乘积存储在B中{返回C,但不反转MP。我们知道,当前值现在是正的,所以&拷贝输入从dÇ'MP 向右后退,即到A上。请记住,阶乘的平方在B中,输入在C中。因此%计算(n-1)!^2 % n,正是我们想要的。!将结果打印为整数(0或1)并@终止程序。


好的,但是那是非高尔夫版本。高尔夫版本呢?您还需要了解有关Hexagony的两件事:

  1. 边缘环绕。如果IP碰到六角形的边缘,它将跳到相反的边缘。当IP直接碰到一个角时,这是模棱两可的,因此碰到角也充当分支:如果当前值为正,则IP跳到其右侧的网格边缘,否则跳到其左侧的网格边缘。
  2. 实际上有6个 IP。它们每个都从一个不同的角开始,沿着边沿顺时针方向移动。一次只有一个处于活动状态,这意味着如果不想使用其他5个IP,就可以忽略它们。您可以使用切换到下一个IP(以顺时针顺序),]并使用切换到上一个IP [。(您也可以通过选择一个特定的对象#,但这是另一次。)

其中还有一些新命令:\/是类似的镜像|,并将~当前值乘以-1

那么非高尔夫版本如何转换为高尔夫版本?线性设置代码)}?}=&{和基本的循环结构可以在这里找到:

        ) } ? } .  ->
       . . . . . .
      . . . . . . .
     . . . . . . . .
->  . = & { . < . . .
     . . . . . > ( <
      . . . . . . .
       . . . . . .
        . . . . .

现在,循环体越过边缘几次,但最重要的是,实际的计算已移交给先前的IP(该IP从左上角开始,向北移动):

        ) . . . .
       = . . . ] .
      } = . . } . .
     ~ . / . * . . .
    . . . . . . . . .
     . . . = . > ( <
      . . } . = . .
       . & . \ [ .
        . . . . .

从分支向东南弹起后,IP绕到边缘到=左上角的两个边缘(它们合起来是无操作),然后从处反弹/。该~反转的电流值,这对于随后的迭代重要的标志。IP再次环绕同一边缘,最后[到达将控制权移交给另一个IP的位置。

现在执行~}=)&}=*}此操作,该操作将取消取反,然后仅运行未循环的循环体(减去=)。最终它命中],从而使双手控制权返回到原始IP。(请注意,下一次,我们将执行该IP,它将从中断处开始,因此它将首先出现在拐角处。我们需要将当前值设为负值,以便IP跳回到西北边缘而不是东南部。)

原始IP恢复控制后,它将从反弹\,执行其余的=,然后命中>以馈入下一个循环迭代。

现在最疯狂的部分是:循环终止时会发生什么?

        ) . . . .
       . ( . . ] =
      . . ' . } . }
     . . . % * . . &
    . . . . . . . . .
     . . . = | . . <
      . . } ! . . .
       . & @ . . .
        . . . . .

IP从向北移动,<并环绕到东北对角线。因此,它最终与循环主体(&}=*}])位于同一执行路径上。这实际上很酷,因为至少在我们添加另一个代码=}(因为}=}等效于{)的时候,这正是我们此时要执行的代码。但是,这又怎么不真正进入先前的循环呢?因为]更改为下一个IP,该IP现在是从右上角开始向西南移动的IP地址(到目前为止尚未使用)。从那里开始,IP沿着边缘继续,环绕到左上角,向下移动对角线,从反弹|并在@执行最后的线性代码位时终止:

=}&)('%!@

)(当然,这是无人操作的-我必须添加,(因为)那里已经存在。)

ew ...真是一团糟...


真好!这有多新?另外,您可能希望每当有一个稳定的版本就创建一个esolangs页面
mbomb007

18
@ mbomb007我在两天前实现了该语言(并在此之前的两三天内对其进行了设计)。是的,我肯定会添加一个esolangs页面,但是我认为规范还不是100%稳定(例如,仍然有3个未分配的命令)。一旦我觉得它更稳定,就将其添加到esolangs和我们的meta post中。
马丁·恩德

在扩展的十六进制下,它环绕到最左角(1。什么1你在说什么吗?
mbomb007'9

@ mbomb007已修复。在)曾经是一个1
马丁·恩德

5
+1只是为了详细说明您的工作方式。如果有更多语言附带的示例,可以使更多人使用它们,:D
jdarling 2015年

66

Pyth,4个字节

}QPQ

打印TrueFalse


12
我知道这已经很老了,但是现在您也可以像这样:P_Q并保存1个字节。
drobilc

14
现在可以实现P_
Blue

3
@drobilc您可以将Q切为EOF,当函数需要一个参数时,它使用输入
Stan Strum

55

视网膜,16字节

^(?!(..+)\1+$)..

在线尝试!

让我们从经典开始:使用regex检测素数。输入应使用任何重复的可打印字符以一元形式给出。为了方便起见,测试套件包括从十进制到一进制的转换。

一个由单行组成的Retina程序将该行视为正则表达式,并打印在输入中找到的匹配项数,这将0用于复合数和质1数。

前瞻确保输入不是复合的:回溯将尝试的每个可能的子字符串(至少2个字符)(..+),然后通过重复在此处捕获的内容,尝试匹配其余输入。如果可能,则表示输入的除数大于1,但小于自身。如果是这种情况,前瞻会导致匹配失败。对于素数没有这种可能性,并且比赛将继续。

唯一的问题是,这种超前行为也可以接受1,因此我们通过使用至少匹配两个字符来排除这种情况..


这实际上是一种不规则的表达方式,因为质数不能构成常规语言。
PyRulez

@PyRulez大多数现实世界中的regex样式都比正则表达式的理论概念强大得多。我改进了措辞。
Martin Ender

1
现在,最强大的“ regex”引擎公开发售,其识别能力与线性有界自动机相同。标准问题正则表达式,模式递归,无限制的headhead和无限制的lookbehint是上下文敏感的解析所需要的(尽管反向引用通常有助于复杂化高效的解析),并且其中的一些都具有它们。甚至不要让我开始使用允许您将代码嵌入正则表达式的引擎。
eaglgenes101

52

CJam,4个字节

qimp

CJam具有用于素数测试的内置运算符。


18
或者:limp
Sp3000

43
pimp我的果酱
瑕疵的

12
pimp是客观的拉皮条客
MickLH 2015年

1
您也可以l~mp
母牛嘎嘎声

12
@Cyoce,q读取输入的一行,i将其解析为整数,并且mp是内置的。CJam有两组包含两个字符的内置程序:“扩展”的内置程序开始e,而“数学”的内置程序开始m
Peter Taylor

47

HTML + CSS,最大 254 + n * 28个字节

我们可以使用正则表达式检查素数。Mozilla具有@document,其定义为:

@document [ <url> | url-prefix(<string>) | domain(<string>) | regexp(<string>) ]# {
  <group-rule-body>
}

根据当前URL通过CSS过滤元素。这是一次通过,因此我们必须执行两个步骤:

  1. 从用户那里获取输入。此输入必须以某种方式反映在当前URL中。
  2. 以尽可能少的代码回复用户。

1.获取输入

我能想到的获取输入并将其传输到URL的最短方法是GET带有复选框的表单。对于正则表达式,我们只需要一些唯一的字符串即可计算外观。

因此,我们从以下内容开始(61个字节):

<div id=q><p id=r>1<p id=s>0</div><form method=GET action=#q>

我们得到两个唯一的<p>s来指示输入的数字是素数(1)还是(0)。我们还定义了表单及其动作。

后跟具有相同名称的n max个复选框(n max * 28个字节):

<input type=checkbox name=i>

紧跟提交元素(34个字节):

<input name=d value=d type=submit>

2.显示答案

我们需要CSS(159字节)来选择<p>要显示的(1或0):

#q,#s,#q:target{display:none}#q:target{display:block}@-moz-document regexp(".*\\?((i=on&)?|(((i=on&)(i=on&)+?)\\4+))d=d#q$"){#s{display:block}#r{display:none}}

»在codepen.io上尝试(仅适用于Firefox)


12
+1:这是我一直以来最喜欢的HTML滥用方式,也是让我喜欢代码高尔夫的那种方式。
2015年

这当然很有趣,但是我不确定它是否满足此挑战的规则。特别是,从理论上讲,我认为它不符合您的算法应适用于任意大整数。您也不能在输入字段的值上使用正则表达式吗?
丹尼斯

@丹尼斯也许。可能甚至。但这并不能解决您提到的问题。我将其保留为非竞争性条目,因为这是最具有挑战性的问题。
mınxomaτ

为什么不?如果您在输入字段中的一元数中有一个数字,则您的代码将不再取决于最大数字。
丹尼斯

4
嗯,我想了更多,只有x个复选框和只有y位数字的解释器之间确实没有区别。忽略我先前的评论。
丹尼斯


40

六边形,28字节

既然Etoplay这个问题上绝对使我震惊,我感到我必须超越他的其他答案

?\.">"!*+{&'=<\%(><.*.'(@>'/

在线尝试!

我使用威尔逊定理,就像马丁在回答中所做的那样:给定n,我输出(n-1!)² mod n

程序在此处展开​​:

   ? \ . "
  > " ! * +
 { & ' = < \
% ( > < . * .
 ' ( @ > ' /
  . . . . .
   . . . .

这是可读版本:

可读性强

说明:

该程序包括三个主要步骤:初始化阶乘输出

六角形的记忆模型是一个无限的六角形网格。我正在使用5个内存位置,如下图所示:

记忆

我将通过它们在该图上的标签来引用这些位置(以及存储在其中的整数)。

初始化:

初始化

指令指针(IP)从左上角开始,向东。内存指针(MP)从IN开始。

首先,?从输入中读取数字并将其存储在IN中。该IP停留在蓝色的路径,通过反映\。该序列"&(MP前后移动(到A),将值从IN复制到A并递减。

IP然后退出六角形的一侧,并且重新进入另一侧(到绿色路径)。它执行'+MP移至B并复制A中的内容<IP重定向到West。

阶乘:

我以特定的方式计算阶乘,因此平方很容易。我同时存储n-1!BC中。

阶乘

指令指针从蓝色路径开始,向东。

='反转的方向MP和向后移动它来Ç。这等效于{=但有=帮助的地方以后会有所帮助。

&{拷贝从值Ç,然后移动MP。该IP然后沿着绿道,什么都不做,达到红色路径,击球之前\和去到橙色的路径。

使用(>,我们递减A并重定向IP East。在这里它打到一个分支:<。对于正A,我们沿着橙色路径继续。否则,该IP将定向到东北。

'*MP移至B并将A * C存储在B中。这是(n-1)*(n-2)初始输入的位置n。的IP然后进入回到初始循环并继续递减和乘法直到达到0。(计算n-1!

注意:在以下循环中,&B中的值存储在C中,因为C中现在存储了一个正值。这对于计算阶乘至关重要。

输出:

输出量

A到达时0。分支将IP沿蓝色路径引导。

=*反转MP并将B * C的值存储在A中。然后,IP退出六边形并重新进入绿色路径。执行"%。这会将MP移至OUT并计算A mod IN(n-1!)² mod n

以下内容{"充当无操作对象,因为它们彼此抵消。!打印最终输出,*+'(并在终止之前执行:@

执行后(输入为5),内存如下所示:

记忆2

控制流的精美图像是使用Timwi的 Hexagony Coloror制作的

感谢Martin Ender生成所有图像,因为我无法在PC上生成图像。


您将这些内存图用于什么?我已经看过Esoteric IDE,但无法运行...
NieDzejkob

@NieDzejkob,最好还是和马丁聊天,因为他还是为我做的。
H.PWiz

@NieDzejkob是的,可以从EsoIDE导出内存图。chat.stackexchange.com/rooms/27364/…如果您想进一步谈谈。
Martin Ender

33

莫宁顿月牙,2448字节

我们回到伦敦!

Take Northern Line to Bank
Take Circle Line to Bank
Take District Line to Parsons Green
Take District Line to Bank
Take Circle Line to Hammersmith
Take District Line to Upney
Take District Line to Hammersmith
Take Circle Line to Victoria
Take Victoria Line to Seven Sisters
Take Victoria Line to Victoria
Take Circle Line to Victoria
Take Circle Line to Bank
Take Circle Line to Hammersmith
Take Circle Line to Cannon Street
Take Circle Line to Hammersmith
Take Circle Line to Cannon Street
Take Circle Line to Bank
Take Circle Line to Hammersmith
Take Circle Line to Aldgate
Take Circle Line to Aldgate
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Aldgate
Take Circle Line to Hammersmith
Take District Line to Upminster
Take District Line to Hammersmith
Take Circle Line to Notting Hill Gate
Take Circle Line to Hammersmith
Take Circle Line to Notting Hill Gate
Take District Line to Upminster
Take District Line to Bank
Take Circle Line to Victoria
Take Circle Line to Temple
Take Circle Line to Aldgate
Take Circle Line to Aldgate
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Pinner
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Pinner
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Pinner
Take Metropolitan Line to Aldgate
Take Circle Line to Hammersmith
Take District Line to Upminster
Take District Line to Victoria
Take Circle Line to Aldgate
Take Circle Line to Victoria
Take Circle Line to Victoria
Take District Line to Upminster
Take District Line to Embankment
Take Circle Line to Embankment
Take Northern Line to Angel
Take Northern Line to Moorgate
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Aldgate
Take Circle Line to Aldgate
Take Circle Line to Cannon Street
Take District Line to Upney
Take District Line to Cannon Street
Take District Line to Acton Town
Take District Line to Acton Town
Take Piccadilly Line to Russell Square
Take Piccadilly Line to Hammersmith
Take Piccadilly Line to Russell Square
Take Piccadilly Line to Ruislip
Take Piccadilly Line to Ruislip
Take Metropolitan Line to Preston Road
Take Metropolitan Line to Aldgate
Take Circle Line to Aldgate
Take Circle Line to Cannon Street
Take Circle Line to Aldgate
Take Circle Line to Aldgate
Take Metropolitan Line to Preston Road
Take Metropolitan Line to Moorgate
Take Circle Line to Moorgate
Take Northern Line to Mornington Crescent

Timwi非常善于在Esoteric IDE中实现控制流站Temple以及Angel在语言规范中添加输入和整数解析。

这可能比“ Hello,World!”打的更好,因为这次我编写了一个CJam脚本来帮助我找到任何两个站之间的最短路径。如果您想使用它(尽管我不知道为什么有人会...),您可以使用在线解释器。粘贴以下代码:

"Mornington Crescent"
"Cannon Street"
]qN/{'[/0=,}$:Q;{Q{1$#!}=\;_oNo'[/1>{']/0="[]"\*}%}%:R;NoQ{R\f{f{\#)}:+}:*},N*

前两行是您要检查的站点。同样,将此粘贴框的内容粘贴到输入窗口中。

输出将显示两个站点上有哪些线路可用,然后显示连接这两个站点的所有站点的列表,并按站点名称的长度排序。它会显示所有这些名称,因为有时最好使用更长的名称,要么是因为它允许使用较短的行,要么是因为电台是特殊的(例如Bank或​​Temple),因此您要避免使用它。在某些极端情况下,两个站点之间没有任何其他站点连接(值得注意的是,大城市和区域线路永不交叉),在这种情况下,您必须找出其他问题。;)

至于实际的MC代码,它基于平方乘方法以及其他许多答案,因为MC具有乘法,除法和模。另外,我认为单循环会很方便。

一个问题是循环是“同时执行”循环,递减和递增很昂贵,因此我无法轻松地计算(n-1)!for n > 0。相反,我正在计算n!,然后最后除以n。我敢肯定有更好的解决方案。

当我开始写这篇文章时,我认为-1在Hammersmith 中存储将是一个好主意,因此我可以更便宜地进行递减,但是最终这可能会花费比节省的更多的钱。如果我有耐心再做一次,则可以尝试-1在Upminster中保持闲逛,以便可以使用Hammersmith获得更有用的功能。


10
伦敦的巡演是否完整?
Rohan Jhunjhunwala

1
@RohanJhunjhunwala 可能
Martin Ender

哇!我喜欢看到经过深思熟虑的问题。我特别喜欢看到必须在哪里编写程序才能编写程序的问题。
Rohan Jhunjhunwala

27

Brachylog(V2),1个字节

在线尝试!

Brachylog(V1),2个字节

#p

这使用内置谓词#p - Prime,将其输入约束为素数。

Brachylog是我制作Prolog的Code Golf版本的尝试,Prolog是使用回溯和统一的声明性代码高尔夫语言。

无内置替代解决方案:14个字节

ybbrb'(e:?r%0)

这是上面代码的细分:

y            The list [0, …, Input]
bbrb         The list [2, …, Input - 1]
'(           True if what's in the parentheses cannot be proven; else false
     e           Take an element from the list [2, …, Input - 1]
     :?r%0       The remainder of the division of the Input but that element is 0
)

1
由于语法短了一个字节,因此您可能也想在文章中编辑Brachylog 2版本。

1
@ ais523是的,完成了。
致命

Brachylog 2回答是否在挑战之后发布?
斯科特·米尔纳

1
@ScottMilner是的,但是在此挑战中明确允许这样做:“与我们的常规规则不同,即使使用的语言(或语言版本)比此挑战新,也可以自由使用它”
Fatalize

26

Haskell,49个字节

对威尔逊定理使用xnor的推论

main=do n<-readLn;print$mod(product[1..n-1]^2)n>0

这样做会不会更短main=interact$\n-> ...
John Dvorak

2
违反直觉,不!考虑到您将需要interact...read在某个地方,这比仅仅需要更长的时间readLn。通常,do符号可能比您期望的更简洁,尤其是当替代方法是lambda时。
林恩

24

迷宫,29字节

1
?
:
}  +{%!@
(:'(
 } {
 :**

从STDIN读取一个整数并输出((n-1)!)^2 mod n威尔逊定理对于这一挑战非常有用。

该程序从左上角开始,首先1将堆栈顶部乘以10并加1。这是迷宫构建大量数字的方式,但是由于迷宫的堆栈中填充了零,因此最终效果就好像我们刚推过1。

?然后n从STDIN 读取并:复制它。}转移n到辅助堆栈,最后用于模数。(然后递减n,我们准备开始计算平方阶乘。

我们的第二个:(重复项)在一个交叉点,在这里迷宫的控制流功能发挥了作用。在执行一条指令后的交界处,如果堆栈的顶部为正,则向右转,为负,则向左转,为零,则向前直行。如果您尝试转弯但撞到墙壁,迷宫会让您转向另一个方向。

对于n = 1,由于堆栈的顶部n递减,或者0,我们直接前进。然后,我们无操作,'然后再减一(,这使我们处于-1。这是负数,因此我们向左转,执行+加号(-1 + 0 = -1),{n从辅助堆栈移回主堆栈,并取%模(-1 % 1 = 0)。然后,我们以输出,!并以终止@

对于n > 1,第二秒:我们向右转。然后,}我们将复制的循环计数器移至辅助堆栈,重复:两次并乘以两次**,然后再将计数器移回{并递减(。如果我们仍然乐观,我们会尝试向右转,但不能转,所以迷宫让我们转而向左转,继续循环。否则,堆栈的顶部是我们的循环计数器,该计数器已减少到0,并将其+添加到计算的((n-1)!)^2。最后,我们n使用{%,输出!和终止返回@

我说这'是一个禁忌,但它也可以用于调试。运行该-d标志,以查看每次'传递时堆栈的状态!


2
平方乘分解是一个很酷的技巧:)
Lynn

@毛里斯谢谢!我需要归功于到期日-我首先在这里
Sp3000,2015年

5
是的,不是我写的第一个迷宫答案!:)
Martin Ender 2015年

24

Bash + GNU实用程序,16

  • @Dennis节省了4个字节

  • @Lekensteyn节省了2个字节

factor|awk NF==2

输入是来自STDIN的一行。对于falsey,输出为空字符串,对于true,输出为非空字符串。例如:

$ ./pr.sh <<< 1
$ ./pr.sh <<< 2
2: 2
$ ./pr.sh <<< 3
3: 3
$ ./pr.sh <<< 4
$

2
很酷,了解了另一个coreutil。您可以通过计算字段数来去除两个字符:factor|awk NF==2
去除

@Lekensteyn-谢谢-由于某些原因,我之前错过了您的评论:)
Digital Trauma

我打算发布一些类似的内容,只是发布时间更长,并且没有AWK。做得很好。
大卫·康拉德

21

Java,126 121字节

我想我们需要记分板的Java答案...所以这是一个简单的试验除法循环:

class P{public static void main(String[]a){int i=2,n=Short.valueOf(a[0]);for(;i<n;)n=n%i++<1?0:n;System.out.print(n>1);}}

与Java通常一样,“完整程序”的要求要比其作为函数的要求大得多,这主要是由于main签名。

展开形式:

class P{
    public static void main(String[]a){
        int i=2,n=Short.valueOf(a[0]);
        for(;i<n;)
            n=n%i++<1?0:n;
        System.out.print(n>1);
    }
}

编辑:修复并在评论中由Peter重新定位。谢谢!


越野车:它报告说1是首要的。否则,删除p并说出将节省4个字符for(;i<n;)n=n%i++<1?0:n;System.out.print(n>0);
Peter Taylor

2
OTOH的class P{public static void main(String[]a){int i=2,n=Short.valueOf(a[0]);for(;i<n;)n=n%i++<1?0:n;System.out.print(n>1);}}作品
Peter Taylor

6
将第3行更改为'long i = 2,n = Long.valueOf(a [0]);`不会导致长度发生变化,但会产生更大范围的有效输入。
James K Polk

4
代替.valueOf您可以使用newnew Short(a[0])或中的new Long(a[0]),它要短一些。
ECS

3
您可以通过使用接口并删除public修饰符来保存4个字节。
RamenChef

18

脑高射炮112 108个字节

({}[()]){((({})())<>){{}<>(({}<(({}[()])()<>)>)<>)<>{({}[()]<({}[()]<({}())>)>{(<()>)}{})}{}{}}}<>{{}}([]{})

在线尝试!

这个怎么运作

最初,第一个堆栈将包含一个正整数n,第二个堆栈将为空。

我们首先将n递减如下。

(
  {}      Pop n.
  [()]    Yield -1.
)       Push n - 1.

n = 1

如果n = 1为零,则while循环

{
  ((({})())<>)
  {
    {}<>(({}<(({}[()])()<>)>)<>)<>{({}[()]<({}[()]<({}())>)>{(<()>)}{})}{}{}
  }
}

被完全跳过。最后,执行剩余的代码。

<>    Switch to the second stack (empty).
{}    Pop one of the infinite zeroes at the bottom.
{<>}  Switch stacks while the top on the active stack is non-zero. Does nothing.
(
  []    Get the length of the active stack (0).
  {}    Pop another zero.
)     Push 0 + 0 = 0.

n> 1

如果n-1非零,我们进入n = 1跳过的循环。这不是一个“真实的”循环。该代码仅执行一次。它实现了以下目的。

{                   While the top of the active stack is non-zero:
  (
    (
      ({})                Pop and push n - 1.
      ()                  Yield 1.
    )                   Push n - 1 + 1 = n.
    <>                  Switch to the second stack. Yields 0.
  )                   Push n + 0 = n.
                      We now have n and k = n - 1 on the first stack, and n on
                      the second one. The setup stage is complete and we start
                      employing trial division to determine n's primality.
  {                   While the top of the second stack is non-zero:
    {}                  Pop n (first run) or the last modulus (subsequent runs),
                        leaving the second stack empty.
    <>                  Switch to the first stack.
    (
      (
        {}                  Pop n from the first stack.
        <
          (
            (
              {}              Pop k (initially n - 1) from the first stack.
              [()]            Yield -1.
            )               Push k - 1 to the first stack.
            ()              Yield 1.
            <>              Switch to the second stack.
          )               Push k - 1 + 1 = k on the second stack.
        >               Yield 0.
      )               Push n + 0 = n on the second stack.
      <>              Switch to the first stack.
    )               Push n on the first stack.
    <>              Switch to the second stack, which contains n and k.
                    The first stack contains n and k - 1, so it is ready for
                    the next iteration.
    {({}[()]<({}[()]<({}())>)>{(<()>)}{})}{}{}  Compute and push n % k.
  }               Stop if n % k = 0.
}               Ditto.

N%ķ使用从42字节的模算法来计算我的除法测试答案中,

最后,我们解释结果以确定n的素数。

<>    Switch to the first stack, which contains n and k - 1, where k is the
      largest integer that is smaller than n and divides n evenly.
      If (and only if) n > 1 is prime, k = 1 and (thus) k - 1 = 0.
{     While the top of the first stack is non-zero:
  {}    Pop it.
}     This pops n if n is prime, n and k - 1 if n is composite.
(
  []    Yield the height h of the stack. h = 1 iff n is prime).
  {}    Pop 0.
)     Push h + 0 = h.

2
您不需要将最后的0弹出堆栈,因为最上面的真实1足够了;您可以通过删除最后一个字节来节省两个字节{}
史蒂文H.

1
嗯,我被撕裂了。一方面,这个问题说输出应该只包含真实值或虚假值,并且1 0两个值。另一方面,只要语言认为它们是真实的或虚假的,我们就会接受数组,并且多个堆栈项是Brain-Flak与数组最接近的东西。可能值得将其带到meta。
丹尼斯

我已经与Brain-Flak的创建者进行了验证,这1 0是事实。chat.stackexchange.com/transcript/message/32746241#32746241
Steven H.


17

R,37 29字节

n=scan();cat(sum(!n%%1:n)==2)

使用审判庭。scan()从STDIN读取一个整数,然后cat()写入STDOUT。

我们生成一个长度n为1到取n模的整数的向量n。我们通过否定(!)来测试每个值是否为0,当数字为0时返回逻辑值,该逻辑值是true,当数字大于0时返回一个逻辑值。逻辑向量的总和是true元素的数量,对于素数,我们期望唯一的非零模为1和n,因此我们期望总和为2。

感谢flodel,节省了8个字节!


有了f=function(x)sum(!x%%1:x)==2它,您可以在28个字节中完成操作。
Mutador

2
@AndréMuta对于这个挑战,所有提交的内容必须是完整的程序,而不仅仅是功能。(还是)感谢你的建议。
Alex A.

17

TI-BASIC,12个字节

2=sum(not(fPart(Ans/randIntNoRep(1,Ans

非常简单。randIntNoRep(给出从1到的所有整数的随机排列Ans

这使规则有些弯曲。因为TI-BASIC中的列表限制为我解释的999个元素

假设输入可以存储在您的数据类型中

因为这意味着可以假定所有数据类型都可以容纳输入。OP同意这种解释。

一个17字节的解决方案,实际上可以达到10 ^ 12左右:

2=Σ(not(fPart(Ans/A)),A,1,Ans

@toothbrush TI-BASIC是一种令牌化语言,因此这里的每个令牌都是一个字节,除了randIntNoRep(两个字节。
lirtosiast

+1啊,我以前从未见过TL-BASIC。感谢您通知我
牙刷

1
虽然,这一个有点不公平,是不是......?我应该写一种只需要1-4个字节(问题ID)和参数的高尔夫语言。它将以其能理解的语言选择最佳答案,执行(传递任何参数),然后返回结果...我想知道这是否违反规则?:-)
牙刷

@toothbrush在TI-BASIC的辩护中:对于解释器,它并不比Pyth和CJam的一个字符命令更不公平,并且TI-BASIC更具可读性。
lirtosiast

1
真正。我不喜欢这些语言,因为几乎所有其他语言的解决方案都更长……尽管我最近用VB6击败了CJam:-]
牙刷

15

PARI / GP,21字节

print(isprime(input))

适用于可笑的大输入,因为这种东西就是PARI / GP的用途。


6
isprime执行APR-CL原始性证明,因此当输入变得非常大时,速度会放慢很多。 ispseudoprime(input)进行AES BPSW可能的素数测试,对于100多个数字,它将更快。35年后仍未发现反例。2002年前的Pari 2.1和更早版本使用了一种可以轻松给出错误结果的不同方法,但是没有人应该使用该方法。
DanaJ

15

TI-BASIC,24字节

请注意,TI-Basic程序使用令牌系统,因此对字符进行计数不会返回程序的实际字节值。

支持Thomas Kwa的回答,这是上乘的。

:Prompt N
:2
:While N≠1 and fPart(N/Ans
:Ans+1
:End
:N=Ans

样品:

N=?1009
                         1
N=?17
                         1
N=?1008
                         0
N=?16
                         0

现在返回,0如果不是素数,1则返回。


3
平方根不只是您实际上不需要该程序正确的优化吗?
马丁·恩德

为什么需要除以二?
Geobits 2015年

我一直很喜欢TI-BASIC的答案。
格兰特·米勒

15

堆栈猫,62 + 4 = 66字节

*(>:^]*(*>{<-!<:^>[:((-<)<(<!-)>>-_)_<<]>:]<]]}*<)]*(:)*=<*)>]

需要使用-ln命令行标志(因此+4个字节)运行。打印0复合数字和质1数。

在线尝试!

我认为这是第一个非同寻常的Stack Cats程序。

说明

快速的Stack Cats简介:

  • Stack Cats在无限的堆栈带上操作,带头指向当前堆栈。每个堆栈最初都填充有无限数量的零。我通常会在用词时忽略这些零,所以当我说“堆栈底部”时,我的意思是最低的非零值;如果我说“堆栈为空”,则意味着它上只有零。
  • 在程序启动之前,将a -1压入初始堆栈,然后将整个输入压入其顶部。在这种情况下,由于该-n标志,输入被读取为十进制整数。
  • 在程序末尾,当前堆栈用于输出。如果-1底部有一个,它将被忽略。同样,由于该-n标志,堆栈中的值仅以换行分隔的十进制整数形式打印。
  • Stack Cats是一种可逆的程序语言:每段代码都可以撤消(没有Stack Cats跟踪明确的历史记录)。更具体地说,要反转任何一段代码,您只需对其进行镜像,例如<<(\-_)变成(_-/)>>。这个设计目标对语言中存在哪些类型的运算符和控制流构造以及可以在全局内存状态上计算哪些类型的功能施加了相当严格的限制。
  • 最重要的是,每个Stack Cats程序都必须是自对称的。您可能会注意到,上述源代码并非如此。这就是-l标志的作用:使用第一个字符为中心,将代码隐式镜像到左侧。因此,实际程序是:

    [<(*>=*(:)*[(>*{[[>[:<[>>_(_-<<(-!>)>(>-)):]<^:>!->}<*)*[^:<)*(>:^]*(*>{<-!<:^>[:((-<)<(<!-)>>-_)_<<]>:]<]]}*<)]*(:)*=<*)>]
    

用整个代码有效地编程是非常不平凡和不直观的,并且还没有真正弄清楚人类如何做到这一点。我们已经强行将这样的程序强制用于更简单的任务,但是无法手工接近该程序。幸运的是,我们找到了一种基本模式,可让您忽略程序的一半。尽管这肯定不是最佳选择,但它是当前在Stack Cats中有效编程的唯一已知方法。

因此,在此答案中,所述模式的模板是这样的(执行方式存在一些可变性):

[<(...)*(...)>]

程序启动时,堆栈磁带如下所示(对于input 4,例如):

     4    
... -1 ...
     0
     ^

[堆栈的顶部向左移动(和磁带头一起)-我们称之为“推动”。然后<仅移动磁带头。因此,在执行前两个命令后,我们遇到了这种情况:

...   4 -1 ...
    0 0  0
    ^

现在,这(...)是一个可以很容易用作条件的循环:只有当当前堆栈的顶部为正数时,才进入和离开该循环。由于当前为零,因此我们跳过了程序的整个前半部分。现在,中心命令为*。这很简单XOR 1,即,它切换堆栈顶部的最低有效位,在这种情况下,将0变为1

... 1 4 -1 ...
    0 0  0
    ^

现在我们遇到了的镜像(...)。这一次,堆栈的顶部是积极的,我们做的输入代码。在研究括号内的内容之前,让我解释一下如何结束:我们要确保在此块的末尾,我们将磁带头重新设置为正值(这样,循环单次迭代之后终止并且被简单地用作线性有条件的),该堆栈向右保持输出和堆权利保持-1。在这种情况下,我们确实离开了循环,>移至输出值]并将其推入,-1因此我们有一个干净的输出栈。

就是这样。现在,在括号内,我们可以执行任何我们想检查原始性的操作,只要确保按末段中的最后一段所述进行设置即可(可以通过推动和移动磁头轻松地完成此操作)。我首先尝试用威尔逊定理解决问题,但最终超过了100个字节,因为平方因数计算实际上在Stack Cats中非常昂贵(至少我没有找到一个捷径)。因此,我改为使用审判庭,事实证明这要简单得多。让我们看一下第一个线性位:

>:^]

您已经看过其中两个命令。此外,:交换当前堆栈的前两个值,^并对第二个值执行XOR运算,将其转换为前一个值。这形成:^了一种常见的模式,可以在空堆栈上复制一个值(我们在该值的顶部拉一个零,然后将其变成0 XOR x = x)。因此,在此之后,我们的磁带部分如下所示:

         4    
... 1 4 -1 ...
    0 0  0
         ^

我实现的试验分割算法不适用于input 1,因此在这种情况下,我们应该跳过代码。我们可以轻松地将映射10正值,而将其他所有值都映射到正值*,因此我们可以这样做:

*(*...)

那就是我们1变成0,如果确实得到了,则跳过大部分代码0,但是在内部,我们立即撤消了,*以便我们取回输入值。我们只需要再次确保在括号的结尾处以正值结尾,以免它们开始循环。在条件内,我们向右移动一个堆栈>,然后开始主试验除法循环:

{<-!<:^>[:((-<)<(<!-)>>-_)_<<]>:]<]]}

花括号(而不是括号)定义了另一种循环:这是一个do-while循环,这意味着它始终至少运行一次迭代。另一个区别是终止条件:进入循环时,Stack Cat会记住当前堆栈的最高值(0在我们的示例中)。然后循环将运行,直到在迭代结束时再次看到相同的值为止。这对我们来说很方便:在每次迭代中,我们只需计算下一个潜在除数的余数,然后将其移到该堆栈上,就可以开始循环了。当我们找到一个除数时,余数为0,循环停止。我们将尝试从开始的除数n-1,然后将其递减到1。这意味着a)我们知道这将在我们到达时终止1b)我们可以通过检查我们尝试的最后一个除数来确定数字是否为质数(如果为1,则为质数,否则为非)。

让我们开始吧。开头有一小段线性部分:

<-!<:^>[:

您知道目前其中大多数功能。新命令是-!。Stack Cats没有递增或递减运算符。但是,它具有-(负数,即乘以-1)和!(按位非,即乘以-1和减)。这些可以合并为一个增量!-,或减少-!。因此,我们递减的副本n在的顶部-1,然后n在堆栈的左侧复制另一个副本,然后获取新的试验除数并将其放在下面n。因此,在第一次迭代中,我们得到了:

      4       
      3       
... 1 4 -1 ...
    0 0  0
      ^

在进一步的迭代中,3将用下一个测试除数替换等等(而此时的的两个副本n将始终是相同的值)。

((-<)<(<!-)>>-_)

这是模运算。由于循环终止于正值,所以我们的想法是从其开始-n并反复添加试验除数d,直到获得正值为止。完成后,我们从中减去结果,d从而得到余数。棘手的一点是,我们不能只是-n在堆栈顶部放一个循环,然后添加一个循环d:如果堆栈顶部为负,则不会进入循环。这就是可逆编程语言的局限性。

因此,为了避免这个问题,我们确实从n栈顶开始,但是仅在第一次迭代时才取反。同样,这听起来比事实简单。

(-<)

当栈顶为正数时(即仅在第一次迭代中),我们用取反-。但是,我们不能只是这样做,(-)因为那样的话,除非应用两次,否则我们不会离开循环-。因此,我们向左移动一个单元格,<因为我们知道那里有一个正值(1)。好的,现在我们已经可靠地否定n了第一次迭代。但是我们有一个新问题:现在,磁带头在第一次迭代中的位置与其他迭代中的位置不同。在继续之前,我们需要巩固这一点。下一步<将磁带头向左移动。第一次迭代的情况:

        -4       
         3       
...   1  4 -1 ...
    0 0  0  0
    ^

在第二次迭代中(请记住,我们已经添加了d一次-n):

      -1       
       3       
... 1  4 -1 ...
    0  0  0
    ^

下一个条件再次合并这些路径:

(<!-)

在第一次迭代中,磁带头指向零,因此将其完全跳过。在进一步的迭代中,磁带头虽然指向一个,所以我们确实执行了此操作,向左移动并在那里增加了单元格。由于我们知道单元格从零开始,因此它现在将始终为正,因此我们可以退出循环。这样可以确保我们始终在主堆栈的左侧留下两个堆栈,并且现在可以向后移动>>。然后在模循环结束时执行-_。你已经知道了-_是减去^XOR:如果堆栈的顶部是,a而其下的值是,b则将其替换ab-a。自从我们第一次否定以来a,就-_用替换ab+a,从而添加了d 进入我们的总营业额

循环结束(达到正值)后,磁带如下所示:

        2       
        3       
... 1 1 4 -1 ...
    0 0 0  0
        ^

最左边的值可以是任何正数。实际上,它是迭代次数减去一。现在还有另一个简短的线性位:

_<<]>:]<]]

就像我之前说的,我们需要减去结果d以获得实际的余数(3-2 = 1 = 4 % 3),所以我们只需要再做_一次即可。接下来,我们需要清理一直在左侧递增的堆栈:当我们尝试下一个除数时,它必须再次为零,以便第一次迭代生效。因此,我们移至该位置,并将该正值与一起推入另一个帮助程序堆栈,<<]然后与另一个帮助程序移回我们的操作堆栈>。我们将dwith 向上拉,:然后将其推回到-1with上],然后使用将剩余部分移到条件堆栈上<]]。这就是试验除法循环的结束:一直持续到我们剩下零为止,在这种情况下,左侧的堆栈包含n最大除数为(n)。

循环结束之后,就*<在我们1再次将路径与输入连接之前。该*只是将零到1,我们将需要在一个位,然后我们转移到与除数<(所以我们是在同一堆栈上为输入1)。

此时,它有助于比较三种不同类型的输入。首先,在特殊情况下n = 1,我们没有完成任何审判部门的工作:

         0    
... 1 1 -1 ...
    0 0  0
         ^

然后,我们前面的示例n = 4,一个复合数字:

    2           
    1    2 1    
... 1 4 -1 1 ...
    0 0  0 0
         ^

最后,n = 3素数:

    3           
    1    1 1    
... 1 3 -1 1 ...
    0 0  0 0
         ^

因此,对于质数,我们1在该堆栈上有一个,对于复合数,我们有一个0大于的正数或正数2。我们使用以下最后一段代码将这种情况转变为01

]*(:)*=<*

]只是将此值向右推。然后*用于大大简化条件情况:通过切换最低有效位,我们将1(prime)变为0,将0(composite)变为正值1,而所有其他正值仍将保持正值。现在我们只需要区分0和肯定。那是我们使用另一个的地方(:)。如果堆栈的顶部是0(并且输入是素数),则只需跳过。但是,如果堆栈的顶部为正(并且输入是一个复合数字),则会将其与交换1,因此我们现在可以0使用复合和1对于素数-只有两个不同的值。当然,它们与我们要输出的内容相反,但这很容易用另一个来解决*

现在,所有剩下的就是恢复预计我们周围的架构堆栈的模式:带头为正值的,导致堆栈到右侧的顶部,和一个-1上的堆栈权。这=<*是为了什么。=交换两个相邻堆栈的顶部,从而将移到-1结果的右侧,例如4再次输入:

    2     0       
    1     3       
... 1 4   1 -1 ...
    0 0 0 0  0
          ^

然后,我们只向左移动,<然后将变成零*。就是这样。

如果您想深入了解程序的工作方式,则可以使用调试选项。添加该-d标志并"在您想要查看当前内存状态的任何位置插入(例如,像这样),或者使用该-D标志获得整个程序的完整跟踪。另外,您可以使用Timwi的EsotericIDE,其中包括带有逐步调试器的Stack Cats解释器。


3
>:^]应该是Stack Cats的官方徽标
Alex A.

14

Haskell,54个字节

import Data.Numbers.Primes
main=readLn>>=print.isPrime

没什么可解释的。


1
使用威尔逊定理,无需外部库就可以达到相同的分数(尽管效率很低):main=do n<-readLn;print$n>1&&mod(product[1..n-1]+1)n<1
Lynn 2015年

9
我们甚至可以做的更短:main=do n<-readLn;print$mod(product[1..n-1]^2)n>049字节。
林恩

4
@毛里斯:很好。请将其作为单独的答案发布。
nimi

14

Ruby,15 + 8 = 23个字节

p$_.to_i.prime?

样品运行:

bash-4.3$ ruby -rprime -ne 'p$_.to_i.prime?' <<< 2015
false

嘿,我知道在Ruby的某个地方会内置一个内置函数,但是我不会费心寻找它,所以我用C. + 1回答。
级圣河

@steveverrill,我知道这是因为对Euler项目有很大帮助。
manatwork 2015年

14

JavaScript,39 36字节

由于ETHproductions节省了3个字节:

for(i=n=prompt();n%--i;);alert(1==i)

对于素数显示为true,否则为false。

用于循环测试每个数N-1 ,直到是一个除数。如果找到的第一个除数为1,则为质数。


先前的解决方案(39个字节):

for(i=n=prompt();n%--i&&i;);alert(1==i)

如何进行不必要的测试:

for(i=2,n=prompt();n%i>0&&i*i<n;i++);alert(n%i>0) //49: Simple implementation: loop from 2 to sqrt(n) to test the modulo.
for(i=2,n=prompt();n%i>0&&i<n;i++);alert(n==i)    //46: Replace i*i<n by i<n (loop from 2 to n) and replace n%i>0 by n==i
for(i=2,n=prompt();n%i&&i<n;i++);alert(n==i)      //44: Replace n%i>0 by n%i
for(i=2,n=prompt();n%i&&i++<n;);alert(n==i)       //43: Shorten loop increment
for(i=n=prompt();n%--i&&i>0;);alert(1==i)         //41: Loop from n to 1. Better variable initialization.
for(i=n=prompt();n%--i&&i;);alert(1==i)           //39: \o/ Replace i>0 by i

我只发布了39个字节的解决方案,因为最好的JavaScript答案已经是40个字节。


2
欢迎来到编程难题和代码高尔夫球!
丹尼斯

2
好答案!在&&i实际上并没有做任何事情,在这个程序中,这样你就可以将其删除。
ETHproductions's

n>1如果您不想1成为素数,则应增加最终条件。
泰特斯(Titus)

1
@Titus如果输入是1for循环,则将执行n%--i一次:1%0返回NaN并停止循环。当alert被调用时i已经等于0所以1==i返回false
Hedi

2
i <2(和一些文本)
Scheintod

13

蜗牛122

输入应以一元形式给出。数字可以是除换行符以外的任何字符混合。

^
..~|!(.2+~).!~!{{t.l=.r=.}+!{t.!.!~!{{r!~u~`+(d!~!.r~)+d~,.r.=.(l!~u~)+(d!~l~)+d~,.l.},l=(.!.)(r!~u~)+(d!~!.r~)+d~,.r.!.

在这种2D模式匹配语言中,程序状态仅由当前网格位置,已匹配的单元格集合以及模式代码中的位置组成。前往相匹配的广场也是非法的。这很棘手,但是可以存储和检索信息。可以通过回溯,传送(t)和断言(=!)来克服针对行进到匹配单元上的限制,这些回溯,传送和断言在完成后不会更改网格。

25的因式分解

奇数合成数的因式分解从标记出一组相互不相邻的单元格开始(图中蓝色)。然后,程序会通过从每个黄色单元格来回穿梭,来验证相邻的蓝色单元格的两侧是否有相等数量的非蓝色单元格。该图显示了必须检查的四个黄色单元之一的这种模式。

带注释的代码:

^                         Match only at the first character
..~ |                     Special case to return true for n=2
!(.2 + ~)                 Fail for even numbers
. !~                      Match 1st character and fail for n=1
!{                        If the bracketed pattern matches, it's composite.
  (t. l=. r=. =(.,~) )+   Teleport to 1 or more chars and match them (blue in graphic)
                          Only teleport to ones that have an unmatched char on each side.
                          The =(.,~) is removed in the golfed code. It forces the
                          teleports to proceed from left to right, reducing the
                          time from factorial to exponential.
  !{                      If bracketed pattern matches, factorization has failed.
    t . !. !~             Teleport to a square to the left of a blue square (yellow in diagram)
    !{                    Bracketed pattern verifies equal number of spaces to
                          the left or right of a blue square.
      {              
        (r!~ u~)+         Up...
        (d!~!. r~)+       Right...
        d~,               Down...
        . r . =.          Move 1 to the right, and check that we are not on the edge;
                          otherwise d~, can fall off next iteration and create and infinite loop
        (l!~ u~)+         Up...
        (d!~ l~)+         Left...
        d ~,              Down...
        . l .             Left 1
      } ,                 Repeat 0 or more times
      l  =(. !.)          Check for exactly 1 unused char to the left
      (r!~ u~)+           Up...
      (d!~!. r~)+         Right...
      d ~,                Down...
      . r . !.
    }
  }
}

13

C,67字节

i,n;main(p){for(scanf("%d",&i),n=i;--i;p=p*i*i%n);putchar(48+p%n);}

如果为,则打印!1(根据Peter Taylor的定义,为假值)0(n-1)!^2 == 0 (mod n)1

编辑:在聊天中进行一些讨论后,puts("!1"+p%n)似乎被认为有点作弊,所以我将其替换了。结果增加了一个字节。

编辑:固定为大投入。

较短的解决方案

56个字节:如pawel.boczarski的注释中所建议,我可以通过读取命令行参数的数量来输入一元:

p=1,n;main(i){for(n=--i;--i;p=p*i*i%n);putchar(48+p%n);}

像这样调用程序

$ ./a.out 1 1 1 1 1
1                        <-- as 5 is prime

51个字节:如果允许通过返回码进行“输出”:

p=1,n;main(i){for(n=--i;--i;p=p*i*i%n);return p%n;}

如我的解决方案所述,可以使用一元表示(命令行参数的数量)来简化您的解决方案。您可以在scanf调用中删除一些字节。
pawel.boczarski

puts("!1"+p%n)您怎么能a+bchar*价值做事?
暴民埃里克

如果字符串"!1"从地址开始a,则在a+1字符串处找到"1"
林恩

@Lynn哦,我认为这是用于连接的(是的,最好将保留给strcat(const char*,const char*)。)。
埃里克Outgolfer

你能改变吗 p=p*i*i%np*=i*i%n
艾伯特·伦肖

12

Python 3,59个字节

现在使用input()代替命令行参数。感谢@Beta Decay

n=int(input())
print([i for i in range(1,n)if n%i==0]==[1])

接受输入input()将使用更短
Beta Decay's

谢谢,我已经用过input()了,但是我忘了刷新答案了。再次感谢!
uno20001 2015年

4
52字节:n=m=int(input())print(all(n%m for m in range(2,n)))
约翰·里昂

1
你是认真的吗。花25个额外的字符以获得la脚的二次加速?这里我们讨厌字节。我们花了每一小时,每一分钟和每一秒钟来摆脱第十九个字节。(开个玩笑。但是我们不做会增加程序长度的时间优化。)
CalculatorFeline

2
使用n%i<1代替。
暴民埃里克

12

APL, 40 13字节

2=+/0=x|⍨⍳x←⎕

使用与我的R答案相同的算法进行试算。我们x从STDIN()分配给输入,并得到余数x除以从1到的每个整数x。将每个余数与0进行比较,这将为我们提供一个由1和0组成的向量,指示哪些整数被除x。使用求和+/可得出除数的数量。如果此数字正好是2,则意味着除数只有1和x,因此x为质数。



12

C ++模板元编程。 166个 131 119字节。

如果常量是质数,则代码会编译,如果复合或1,则代码不会编译。

template<int a,int b=a>struct t{enum{x=t<a,~-b>::x+!(a%b)};};
template<int b>struct t<b,0>{enum{x};};
int _[t<1>::x==2];

(除最后一行外,所有换行符均在“实际”版本中删除)。

我认为“编译失败”是元编程语言的虚假返回值。请注意,它不会作为完整的C ++程序链接(因此,如果将其作为素数输入,则会出现链接错误)。

要测试的值是最后“行”上的整数。

现场例子

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.