这个数字是阶乘吗?


38

任务

给定一个自然数作为输入,您的任务是根据输入是否为任何自然数的阶乘来输出真值或假值。您可以假定输入数字将始终在您的语言支持的数字范围内,但是您一定不能滥用本机数字类型来解决问题

适用标准漏洞


输入值

系统会为您提供自然数(类型Integer或类似数字)。

您可以采用任何所需的输入方式,但前提是要假定其位于预定义变量中。prompt允许从文件,控制台,对话框(),输入框等进行读取。也可以作为函数参数输入!


输出量

您的程序应根据输入数字是任何自然数的阶乘来输出真实或错误值。

确保所有输入的真实/假值都一致,即,如果您使用一对1和0分别表示真实和假值,那么您的程序必须为应该具有真实值的所有输入输出1,而对于所有输入则为0。所有应具有假值的输入。

除了将其写入变量之外,您可以采用任何所需的输出方式。允许写入文件,控制台,屏幕等。功能也return被允许!

您的程序不得对任何输入产生错误!


测试用例

Input     Output

1         Truthy (0! or 1!)
2         Truthy (2!)
3         Falsey
4         Falsey
5         Falsey
6         Truthy (3!)
7         Falsey
8         Falsey
24        Truthy (4!)
120       Truthy (5!)

获胜标准

这是,因此以字节为单位的最短代码胜出!


2
如果该语言仅支持{0,1}范围内的数字,我是否可以期望输入始终为1
eush77

11
@ eush77 默认情况下,禁止使用本机数字类型来解决问题
丹尼斯

1
是4!是真的吗?
tuskiomi

问题:为什么不使用I / O默认值?
CalculatorFeline

Answers:


37

Brachylog,1个字节

在线尝试!

说明

是内置的,它断言以下关系:其输出是其输入的阶乘。我们只给它一个设定的输出,看看它是否通过可变输入获得成功。


6
@BetaDecay那是因为它是在Prolog中打印的方式(这与事实true.是陈述而true不是事实有关)
Fatalize

6
这是一个微不足道的解决方案,但是由于序言的工作方式,它很聪明。
硕果累累


17
首先是自定义语言,然后是自定义编码。我们已经完全颠覆了这些有趣问题的全部重点
亚历山大

13
@Alexander自定义编码与您正在谈论的任何问题都不相关。我可以改用任何“现有”编码,它仍然是1个字节。它只是可读性差得多。
Fatalize '17

19

果冻,3个字节

!€ċ

在线尝试!

1表示是,0表示否。

这个怎么运作

!€ċ  argument as z
!€   [1!, 2!, 3!, ..., z!]
  ċ  count the number of occurrence of z

19

果冻,4字节

Œ?IE

不是最简短的果冻答案,而是相当有效的答案。

在线尝试!

这个怎么运作

Œ?IE  Main link. Argument: n

Œ?    Yield the n-th permutation of the positive integers, without the sorted tail.
      For 120, this yields [5, 4, 3, 2, 1], the tail being [6, 7, 8, ...].
  I   Increments; compute all forward differences.
      For 120, this yields [-1, -1, -1, -1].
   E  Check if all differences are equal.

2
因为我们编码高尔夫球手关心效率。
Okx

12
如果我自己说的话,这是一个巨大的复杂性改进,只花了一个字节的代价,并且是对内置函数的巧妙使用。¯\ _(ツ)_ /¯–
丹尼斯

有趣的是,对于0,它返回true,而@LeakyNun的3字节答案,尽管通常要慢得多,但对于0,它正确地返回false。在有效执行时间答案中,是否需要额外的字节来为0返回false?
Deadcode

@Deadcode检查0将需要两个额外的字节。如果不确定OP的“自然数”定义是否包含0。测试用例不...
丹尼斯

17

ECMAScript的正则表达式,733+ 690+ 158 119 118 (117🐌)字节

经过超过4½年的不活动时间,我对正则表达式的兴趣激起了新的活力。因此,我一直在寻找更自然的数字集和函数以与一元ECMAScript正则表达式匹配,继续改进我的正则表达式引擎,并且也开始研究PCRE。

我着迷于ECMAScript正则表达式中构造数学函数的异同。必须从完全不同的角度来解决问题,直到关键的见识到来之前,才知道这些问题是否完全可以解决。它迫使铸造一个更宽的网,以发现哪些数学特性可以用来解决特定问题。

匹配阶乘数是我什至在2014年甚至没有考虑解决的问题-或者如果我只是暂时将其排除在外,那就太不可能了。但是上个月,我意识到可以做到。

与我在其他ECMA regex帖子中一样,我会警告:我强烈建议学习如何在ECMAScript regex中解决一元数学问题。对于我而言,这是一次引人入胜的旅程,对于那些可能想要自己尝试的人,尤其是对数字理论感兴趣的人,我都不想破坏它。请参阅此较早的帖子,以获取一系列连续扰流器标记的建议问题的列表,以逐一解决。

因此,如果您不想破坏一些高级一元正则表达式魔术,请不要再继续阅读。如果您确实想自己弄清楚该魔术,我强烈建议您先解决ECMAScript regex中的一些问题,如上面链接的那部分所述。

这是我的主意:

与大多数其他方法一样,与此数字集进行匹配的问题在于,在ECMA中,通常不可能在循环中跟踪两个变化的数字。有时它们可​​以多路复用(例如,可以将相同基数的功率明确地加在一起),但这取决于它们的属性。因此,我不能只是从输入数字开始,然后将其除以递增的红利,直到达到1(或者至少我以为如此)。

然后,我对阶乘中素数的多重性进行了一些研究,并了解到有一个公式可用于 ECMA正则表达式中!

经过一段时间的研究,并同时构建了其他一些正则表达式后,我承担了编写阶乘正则表达式的任务。花了几个小时,但最终效果很好。另外,算法可以将反阶乘作为匹配返回。甚至没有回避的机会。由于必须在ECMA中实施该方法的本质,因此有必要在做任何其他事情之前先猜测一下逆阶乘是什么。

缺点是该算法需要很长的正则表达式...但是我很高兴它最终需要在我的651字节乘法正则表达式中使用一种技术(该方法最终被淘汰了,因为使用了50字节正则表达式)。我一直希望出现一个需要此技巧的问题:通过明确地将它们加在一起并在每次迭代中将它们分开,循环使用两个数字,它们都是同一个基数的幂。

但是由于该算法的难度和长度,我使用了分子前行(形式为(?*...))来实现它。这不是ECMAScript或任何其他主流正则表达式引擎中的功能,而是我在引擎中实现的功能。在分子前瞻内部没有任何捕获,它在功能上等同于原子前瞻,但是有了捕获,它可能会非常强大。引擎将回溯到前瞻,并且可以用来推测一个值,该值循环所有可能性(以供以后测试),而不会消耗输入字符。使用它们可以使实现更清洁。(可变长度后视至少在功能上等同于分子先行,但后者往往会带来更直接,更优雅的实现。)

因此733和690字节的长度实际上并不能表示该解决方案的ECMAScript兼容版本-因此后面是“ +”;肯定有可能将该算法移植到纯ECMAScript中(这会大大增加其长度),但是我却没有解决它……因为我想到了一个更简单,更紧凑的算法!一种无需分子先行即可轻松实现的方法。它也明显更快。

像以前一样,这个新的必须对逆阶乘数进行猜测,循环遍历所有可能性并测试它们是否匹配。它将N除以2,以为其需要做的工作腾出空间,然后播种一个循环,在该循环中,它将反复用除以3的除数重复该输入,并每次递增。(因此,1!和2!不能与主算法匹配,必须分开处理。)除数通过将其添加到运行商中来保持跟踪;这两个数字可以明确分开,因为假设M!== N,运行商将继续被M整除,直到等于M。

这个正则表达式在循环的最内部进行除数运算。除法算法与我的其他正则表达式相同(并且类似于乘法算法):对于A≤B,仅当C%A = 0且B是满足B≤C的最大数时,A * B = C(如果有) C%B = 0且(CB-(A-1))%(B-1)= 0,其中C是除数,A是除数,B是商。(对于A≥B的情况,可以使用类似的算法,并且如果不知道A与B的比较,则只需进行一次除数检验。)

因此,我很喜欢这个问题能够比我的高尔夫优化斐波那契正则表达式减少甚至更少的复杂性,但是令我感到失望的是,我的相同基数的多路复用功率技术必须等待另一个问题实际上需要它,因为这一点不需要。这就是我的651字节乘法算法被一个50字节的算法取代的故事!

编辑:我能够使用格里米(Grimy)发现的技巧来丢弃1个字节(119→118),该技巧可在商被保证大于或等于除数的情况下进一步缩短除法。

事不宜迟,这里是正则表达式:

正确/错误版本(118字节):

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$|^xx?$

在线尝试!

返回阶乘或不匹配(124字节):

^(?=((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$)\3|^xx?$

在线尝试!

ECMAScript +\K(120字节)返回反阶乘或不匹配:

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\K\3$|^xx?$

以及带有注释的自由空间版本:

  ^
  (?=                           # Remove this lookahead and the \3 following it, while
                                # preserving its contents unchanged, to get a 119 byte
                                # regex that only returns match / no-match.
    ((x*)x*)(?=\1$)             # Assert that tail is even; \1 = tail / 2;
                                # \2 = (conjectured N for which tail == N!)-3; tail = \1
    (?=(xxx\2)+$)               # \3 = \2+3 == N; Assert that tail is divisible by \3
    # The loop is seeded: X = \1; I = 3; tail = X + I-3
    (
      (?=\2\3*(x(?!\3)xx(x*)))  # \5 = I; \6 = I-3; Assert that \5 <= \3
      \6                        # tail = X
      (?=\5+$)                  # Assert that tail is divisible by \5
      (?=
        (                       # \7 = tail / \5
          (x*)                  # \8 = \7-1
          (?=\5(\8*$))          # \9 = tool for making tail = \5\8
          x
        )
        \7*$
      )
      x\9                       # Prepare the next iteration of the loop: X = \7; I += 1;
                                # tail = X + I-3
      (?=x\6\3+$)               # Assert that \7 is divisible by \3
    )*
    \2\3$
  )
  \3                            # Return N, the inverse factorial, as a match
|
  ^xx?$                         # Match 1 and 2, which the main algorithm can't handle

我对这些正则表达式进行高尔夫优化的完整历史记录在github上:

用于匹配阶乘数的正则表达式-多重比较方法,带有分子lookahead.txt
用于匹配阶乘数.txt的正则表达式(上面显示的一个)

请注意,((x*)x*)可以将其更改为((x*)+),将大小减小1个字节(至117个字节),而不会丢失正确的功能-但是正则表达式的响应速度呈指数级增长。但是,此技巧虽然可在PCRE和.NET中使用,由于在循环中遇到零长度匹配时的行为无法在ECMAScript 中使用((x+)+)可以在ECMAScript中工作,但这会破坏正则表达式,因为对于,需要捕获的值(将正则表达式更改为1索引将使高尔夫球失去这种好处)。n=3!3 3 = 0\233=0

.NET regex引擎不会在其ECMAScript模式下模拟此行为,因此117字节的regex可以工作:

在线尝试! (指数级减速版本,带有.NET正则表达式引擎+ ECMAScript仿真)


14

JavaScript(ES6),30 29 28字节

期望一个正整数。-1为虚假和-2真实返回。

f=(n,k=2)=>n>1?f(n/k,k+1):~n

console.log(1,  '-->',f(1))   // Truthy (0! or 1!)
console.log(2,  '-->',f(2))   // Truthy (2!)
console.log(3,  '-->',f(3))   // Falsey
console.log(4,  '-->',f(4))   // Falsey
console.log(5,  '-->',f(5))   // Falsey
console.log(6,  '-->',f(6))   // Truthy (3!)
console.log(7,  '-->',f(7))   // Falsey
console.log(8,  '-->',f(8))   // Falsey
console.log(24, '-->',f(24))  // Truthy (4!)
console.log(120,'-->',f(120)) // Truthy (5!)

注意:此函数支持相当大的输入(您应将其读取为:“ JS非常大”)。它应该安全了工作2 53 - 1。肯定会从N = 121,645,100,408,831,992开始失败,此输入舍入为19!= 121,645,100,408,832,000,因为其IEEE-754编码。有可能是先于其他假阳性结果121,645,100,408,831,991由于舍入误差的,但我不知道。


很好-真的很喜欢使用~末尾。
史蒂夫·本内特

您可以编辑以便我取消投票吗?(如果您想知道为什么我投票失败,那是因为我忘记了这个问题的不寻常的I / O规则。)
CalculatorFeline

@Arnauld尚未投票。
CalculatorFeline

11

Python 3中39 38个字节

f=lambda n,i=1:n>1and f(n/i,i+1)or n<1

递归函数取的整数,n,inversley表示结果返回一个布尔值(truthy:False,falsey: True

在线尝试!

反复分裂n通过i,具有的初始值1,直到剩余小于或等于1然后测试如果余数是小于1,仅阶乘将与剩余结束等于1,和<是一个字节短于==


@ovs我们被限制为两个一致的输出。不幸的是,1除了1它返回之外,所有阶乘都返回True
乔纳森·艾伦

11

Java 8,46字节

i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;}

这是基于RomanGräf的条目,我能够将其打掉十几个字节。我会在那里建议的,但我没有足够的声誉来发表评论!我修改后的测试运行器代码:

import java.util.function.Function;
import java.util.stream.IntStream;

public class IsFactorial {
    public static Function<Integer, Boolean> isFactorial = i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;};
    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};
    public static void main(String[] args){
        System.out.println(
            IntStream.of(truthyCases).allMatch(i->isFactorial.apply(i)) &&
            IntStream.of(falsyCases).allMatch(i->!isFactorial.apply(i)));
    }
}

9

视网膜50 38字节

@Neil通过缩短循环并摆脱了循环,从而节省了12个字节 ;

.+
1¶$&$*
+`^(1+)¶(\1)+$
1$1¶$#2$*
¶.$

在线尝试!

输出1为true和0false。

.+ 匹配整数

1¶$&$*将其替换为1后跟换行符,然后将匹配项转换为一元

剩下的程序通过连续增加正整数在底行中除一进制数,并在顶行中保持跟踪,尽管有可能这样做。

+` 循环直到字符串保持不变

  • ^(1+)¶(\1)+$匹配最上面一行的1s和1最下面一行的许多的倍数,并替换为

  • 1$1¶$#2$*顶行要多1一个1,即将顶行所代表的数字加1,然后再换行和底行中顶行的匹配数(即第二个捕获组的匹配计数) )many 1s,也就是说,将底数除以顶数

一旦不再可能,

¶.$给出此正则表达式的匹配数,即。1底线是否存在孤独,仅当数字是阶乘时才会发生


如果允许没有崩溃/崩溃而不是真实/虚假值,那么我可以获得36 34个字节。

^
1¶
{`.+$
$*
^(1+)¶(\1)+$
1$1¶$#2

这采用相同的方法,但将$*合并为第三和第四行。第三行以后是相同的环的一部分,{是对于短+(其中(基团的剩余行到回路。阶乘以程序结束循环而结束,而非阶乘则永远卡在循环中,直到Retina抛出由最后一次替换失败导致的OverflowException,从而使底数为一进制而不是十进制,并且第一次替换循环将底线从十进制转换为一元,因此很快就会爆炸。


通过删除替换结束1时隐含的字节来保存字节$*
尼尔

更好的是,将结合$*其他两行。
尼尔


3
令您印象深刻的是,您找到了一种有条件地使视网膜崩溃的方法。:)
马丁·恩德

2
您能补充说明吗?
CalculatorFeline

8

05AB1E,4个字节

L!QO

在线尝试!

说明

L      # range [1 ... input]
 !     # calculate factorial of each
  Q    # compare with input for equality
   O   # sum

1
因为L弹出输入,您是否不需要首先复制输入?此外,还会Å!为您提供一个小于或等于输入的阶乘列表。
尼尔·

@NeilA。幸运的是,如果堆栈上没有足够的参数来执行操作,那么输入会再次弹出,因此我D在这里不需要。好赶上Å!。我总是忘了列表命令。它不会保存任何字节,但是肯定会更有效。
Emigna '17

我不知道输入会再次弹出...那肯定可以节省很多字节。
尼尔·

@NeilA。这是一个相当新的功能。我认为它是在不到一个月前添加的。
Emigna '17

8

C ++,102 100 92个字节

#include<cmath>
int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}

循环遍历从0到的所有值n并计算阶乘,然后检查其是否等于n

谢谢克里斯托夫!(保存8个字节)


嗨!欢迎来到PPCG!不错的第一答案!祝未来好运!
Arjun

不错的第一答案!您可以像这样保存一些字节:int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}lround并且lgamma已经是C ++ 11,因此可以简单地实现#include<cmath>。也许您甚至可以进一步完善我的建议:)
Christoph

7

Haskell43个 26字节

f n=elem n$scanl1(*)[1..n]

在线尝试!

  • 感谢Laikoni,节省了17个字节

2
f n=elem n$scanl1(*)[1..n]是荒谬的低效率,但较短。
Laikoni '17

没有关于代码效率的规则吗?
sudee

1
我所不知道的。代码高尔夫要求以尽可能少的字节数提供解决方案,而无需任何效率声明。同样在我的机器上,该功能正常运行,40430没有明显的延迟。
Laikoni '17

我的意思是“解决方案应在合理的时间范围内终止”,但我认为这两种方法都符合要求。谢谢!
sudee

1
漂亮又简单。我以为我可以用师说做的更好,divMod通过[1..]先后直至达到零余数为1(因子)的商或非零余数(非阶乘),但它似乎不正确的方法。不过,我确实找到了这个可爱的46个字符的解决方案:f|let x%n=mod n x==0&&(x+1)%div n x||n==1=(1%)
乔恩·普迪

6

Haskell,38个字节

m#n=n<2||mod n m<1&&(m+1)#div n m
(2#)

在线尝试!用法示例:(2#) 24。返回TrueFalse

这是我可以获得的最短的时间,同时仍然非常高效。即使对于最大的数字

145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000

结果立即给出。该解决方案通过将输入除以结果nm = 2,3,4,5,...直到结果为1或被n整除m

对于其计算较短,但令人难以置信的低效率的26个字节的解决方案n!对于那些不投入阶乘看这里



5

傅立叶40 39字节

I~Q1~N(i^~i*N~N{Q}{1~Xo}N>Q{1}{1~X0o}X)

在FourIDE上尝试!

基本上将数字N乘以增加的量,直到N等于输入的(输出1)或大于输入(输出0)。

伪代码说明:

Q = Input
N = 1
While X != 1
    i += 1
    N = N*i
    If N = Q Then
        Print 1
        X = 1
    End If
    If N > Q Then
        Print 0
        X = 1
    End If
End While

5

Japt8 6字节

ol x¥U

在线尝试!

这将输出0表示false,1表示true。

说明

 ol x¥ U
Uol x==U
Uo       # Create the range [0 ... input]
  l      # Replace each element by its factorial
     ==U # Compare each element to the input (yielding 1 if equal and 0 otherwise)
    x    # And sum the result

1
我真的应该添加一个内置的“包含”:P
ETHproductions's

1
哦,嘿,您可以更改aU ¦Jx¥U(将每个映射XX==U总和),尽管它不适用于TIO。
ETHproductions's

失败的2监守o只会给你[0,1]这是节省1个字节的修复程序
毛茸茸的

4

Perl 5,31个字节

$a=<>;$a/=++$i while$a>1;exit$a

输入通过STDIN获得,输出通过退出代码提供(阶乘为1,非阶乘为0)。

输入被连续的整数除,直到它等于1或小于1的小数,然后被截断为结果。


-5个字节的TIO
Nahuel Fouilleul

4

Perl 6、29个字节

{($_,{$_/++$}...2>*).tail==1}

测试一下

展开:

{   # bare block lambda with implicit parameter 「$_」

  (              # generate a sequence

    $_,          # starting with the input

    {
      $_ / ++$   # divide previous element by an ever increasing number
                 # 1,2,3,4,5,6,7,8 ... *
    }

    ...          # keep generating until

    2 > *        # 2 is greater than what was generated
                 # ( 1 or a fractional number )

  ).tail == 1    # check if it ended at 1
}

17个字节:{$_∈[\*] 1..$_}。另一个有趣的方法是2>*.polymod(1..*).sum
nwellnhof '18

4

setlX,32字节

f:=n|=>exists(x in{0..n}|n==x!);

创建一个名为的函数f,您可以在其中使用潜在的阶乘作为参数。

它可以使用任意整数大小工作,但是效率很低。

(顺便说一句:这是我第一次参加编程难题)




4

C#(.NET Core),68字节

bool f(System.Numerics.BigInteger n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

在线尝试!

这不是最短的解决方案,但是可以处理大量的问题。TIO链接包含一个示例10000!

这是使用的较短版本,int最大值为2147483647

C#(.NET Core),45字节

bool f(int n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

在线尝试!

感谢@KevinCruijssen在两个答案中总共打了3个字节!


2
所述&&可golfed到&,并且后;不必进行计数为lambda函数。此外,不能ulong k=2uint k=2你的50个字节的答案吗?
凯文·克鲁伊森

1
&vs 很好&&。我以为我正在堆栈溢出,但是毕竟它似乎可以工作。ulong是64位,uint而是32 位。看起来其他人正在使用,int所以也许我将其用于简短版本。关于尾随;,这些是完整功能,而不是lambda,所以我认为我需要包括它们吗?
dana

这真是奇怪.NET如何解决/%之间ulonguint,但不ulongint。不知道:)
dana

1
@Oliver- double在某些时候您开始看到舍入-例如24!和120!失败。虽然System.Numerics.BigInteger精度最高,int但答案最短:)
dana

1
@Deadcode-您大约是0 :)根据挑战中的示例,我将“自然数”解释为1,2,...。我同意在现实世界中,最好使用短路&&运算符。但这是代码高尔夫;)很高兴您喜欢这个10000!例子!
dana

4

C ++(clang),51个字节

只要打高尔夫球,递归都会胜出。

51个字节,零为true:

int f(int n,int i=2){return n<2?!n:n%i|f(n/i,i+1);}

1字节的节省会牺牲很多速度。更换|||,使之快,由于逻辑或短路的评价。

在线尝试!(51字节慢速版本)
在线尝试!(52字节快速版)

非高尔夫慢速版本:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    // Because any nonzero value represents "false", using "|" here is equivalent
    // to "||", provided that the chain of recursion always eventually ends. And
    // it does always end, because whether or not "n" is factorial, the "n / i"
    // repeated division will eventually give the value of zero or one, satisfying
    // the above condition of termination.
    return (n % i) | isFactorial(n / i, i+1);
}

非高尔夫快速版本:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    if (n % i != 0)
        return 1; // not factorial
    else
        return isFactorial(n / i, i+1);
}

有很多方法可以重新安排此操作。

52个字节,非零为true:

int f(int n,int i=2){return n<2?n:n%i?0:f(n/i,i+1);}

在线尝试!

52个字节,零为true:

int f(int n,int i=2){return!n?1:n%i?n-1:f(n/i,i+1);}

在线尝试!

在求助于递归之前,我尝试制作一些迭代版本,但它们接近。

54个字节,非零为true:

int f(int n){for(int i=2;n>1;)n=n%i?0:n/i++;return n;}

在线尝试!

54个字节,零为true(基于RomanGräf的Java 8提交):

int f(int n){int a=1,i=0;for(;a<n;a*=++i);return a-n;}

在线尝试!

现在,对于桶的底部,没有任何n==0处理的递归版本(我认为它们是无效的,因为0是自然数,任何不使用它的定义都不会限制“自然数”的使用)。在以下版本中,f(0)由于堆栈溢出而导致的无限递归触发segfault,或者使用将其优化为迭代的编译器无限循环:

48个字节,零为true:

int f(int n,int i=2){return n%i?n-1:f(n/i,i+1);}

在线尝试!

48字节,零为true(基于Hagen von Eitzen的33字节C(gcc)提交):

int f(int n,int e=0){return n%++e?n-1:f(n/e,e);}

在线尝试!


50 编辑:49,无需递归。
Grimmy

回到递归48。您可能不会喜欢这种方式,而是使用全局变量44
Grimmy

3

Mathematica,20个字节

!FreeQ[Range[#]!,#]&

其他版本来测试大数(请参阅评论)

Range[10^3]!~MemberQ~#&

测试多达1000个!


2
据我了解的问题,Mathematica是否有能力接受1001!作为输入,则不符合规范。
彼得·泰勒

2
您甚至可以保存三个字节,同时使其对所有输入均有效。只需将10 ^ 3替换为#; 您可以使用Range @#节省另一个字节
Julien Kluge

@Julien Klugethen寻找1243234将会花很长时间……
J42161217

1
我认为您可以通过替换Range[#]Range@#:) 来节省另一个字节:
numbermaniac

3
看起来您可以使用infix语法保存另一个字节:!Range@#!~FreeQ~#&
numbermaniac

3

Cubix,24字节

U0O@1I1>-?1u>*w;W;@Orq)p

在线尝试

集中化

    U 0
    O @
1 I 1 > - ? 1 u
> * w ; W ; @ O
    r q
    ) p

我们通过推动启动1INPUT,1压入堆栈。这些将分别是我们的索引,目标和累加器。

然后,我们循环。在每次迭代中,我们从输入中减去累加器。如果结果为0,则说明已完成,因此我们按下1Output并退出。如果为负,则说明我们走得太远,因此我们按0Output并退出。否则,我们看到

;p)*rq;
;         Pop the difference off the stack.
 p)       Move the index to the top of the stack and increment it.
   *      Multiply the accumulator by the index to get the next factorial.
    rq;   Put the stack back in the right order.

3

Neim,8字节

𝐈Γ𝐈𝐩₁𝔼)𝐠

说明:

Example input: 6
𝐈         Inclusive range [1 .. input]
          [1, 2, 3, 4, 5, 6]
 Γ        For each...
  𝐈         Inclusive range [1 .. element]
            [[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6]]
   𝐩        Product
            [1, 2, 6, 24, 120, 720]
     𝔼      Check for equality with
    ₁       the first line of input
            [[0, 0, 1, 0, 0, 0]]
      )   End for each
       𝐠  Select largest element
          [1]

试试吧!

内姆,3个字节(非竞争)

进行挑战后,添加了非竞争性的contains令牌和阶乘令牌。

𝐈𝐓𝕚

说明:

Example input: 6
𝐈     Inclusive range [1 .. input]
      [[1, 2, 3, 4, 5, 6]
 𝐓    Factorial each
      [[1, 2, 6, 24, 120, 720]]
  𝕚   Check that the [cycled] input is in the list
      [1]

试试吧!


3

> <>24 22字节

-2个字节,感谢@Aaron

我正在尝试一种新语言(因为我的Mathematica许可已过期…)

01\{=n;
?!\$1+:@*:{:}(

在线或在鱼游乐场尝试

假设输入数字已经在堆栈上,并返回0或1。它的工作方式是将前n个数字相乘,直到不再小于输入为止;然后,如果等于输入,则输出1;如果不等于输入,则输出0。 t。


你可以把你v>\n<^变成\\n/; 看到这里
亚伦

@Aaron,太好了,谢谢!
不是一棵树

3

APL(Dyalog Unicode),5 6 7字节

通过改变Golfed一个字节×/,以!感谢埃里克Outgolfer

⊢∊!∘⍳

在线尝试!

说明

                          Range of numbers from 1 to argument, 1 2 3 4 .. n
   !                       Factorial; 1! 2! 3! 4! .. n!
⊢∊                         Is the right argument a member of this list?

累计金额?
Leaky Nun

@LeakyNun已修复
Kritixi Lithos

GNU APL 1.2中的一个额外字节N∊×\⍳N←⎕如何接受参数?我什么都看不到n。这是Dyalog特有的东西吗?
Arc676 '17

2
@ Arc676我的解决方案是火车,您可以这样称呼它:(⊢∊(×/⍳)) right_argument在TIO链接中可以看到。而指正确的论点。
Kritixi Lithos'5

注意:AGL将为您节省一个字节;⊢∊×\ä⍳。“正确”(但更长)的解决方案是0=1|!⍣¯1;“逆阶乘是整数吗?”
2015年

2

JavaScript(ES6),71个字节

这将输入作为函数参数并alert输出。输出0为假和1为真。

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}alert(r)}

说明

该程序包含两个功能,fgf是递归阶乘计算函数,并且g是程序的主要功能。g 假设有一个参数n。它定义了一个默认参数r,其值为0,以及另一个默认参数,其值为0。然后,它对从0到的所有Integer进行n迭代,并在每次迭代中检查f应用于i(当前索引)的函数是否等于n,即是否n为的阶乘i。如果出现这种情况是这种情况,r的值被设置为1.在函数结束时,ralert

测试片段

注意: 片段输出使用的console.log()人讨厌那些讨厌alert()的人。

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}console.log(r)}

g(1)
g(2)
g(3)
g(4)
g(5)
g(6)
g(7)
g(8)
g(24)
g(120)


评估可能比使用代码块短。
Downgoat '17

@Downgoat我应该怎么做?对不起,如果太明显了!:P
Arjun

2

QBIC21 19字节

[:|q=q*a~q=b|_x1}?0

说明

[:|     Start a FOR loop from 1 to n
q=q*a   q starts as 1 and is multiplied by the FOR loop counter
        consecutively: q=1*1, *2, *3, *4 ... *n
~q=b|   If that product equals n
_x1     Then quit, printing a 1
}       Close the IF and the FOR
?0      If we're here, we didn't quit early and didn't find a factorial, print 0

先前

[:|q=q*a┘c=c+(q=b)}?c

说明:

[:|         Start a FOR loop from 1 to n
q=q*a       q starts as 1 and is multiplied by the FOR loop counter
            consecutively: q=1*1, *2, *3, *4 ... *n
┘           Syntactic line break
c=c+        c starts out at 0 and then keeps track of 
    (q=b)       how often our running total == n
}           Closes the FOR-loop
?c          Print c, which is 0 fir non-factorials and -1 otherwise.

2

Java 8,59字节

i->{for(int j=1,c=0;j<=i;j*=++c)if(j==i)return 1;return 0;}

测试码

import java.util.function.IntFunction;
import java.util.stream.IntStream;

public class IsFactorial
{
    public static IntFunction<Integer> isFactorial = i->
    {
        for(int j=1,c=0;j<=i;j*=++c)
            if(j==i)return 1;return 0;
    };

    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};

    public static void main(String[] args)
    {
        System.out.println
        (
            IntStream.of(truthyCases)
                .allMatch(i->isFactorial.apply(i)==1)
            && IntStream.of(falsyCases)
                .allMatch(i->isFactorial.apply(i)==0)
        );
    }
}
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.