阶乘和永无止境的循环!


33

如您所知,正整数的阶乘n是等于或小于的所有正整数的乘积n

例如 :

6! = 6*5*4*3*2*1 = 720
0! = 1

现在,我们将定义一个不相关名称的特殊操作,例如sumFac

给定正整数nsumFac(n)是数字的阶乘之和。

例如 :

sumFac(132) = 1! + 3! + 2! = 9

任务

您的任务(无论是否选择接受)都是将应用的序列(可能是无限的)返回sumFac给输入中给定的整数。

范例: 132 -> 132, 9, 362880, 81369, 403927, ...

但这还不是全部!确实,的应用sumFac最终将创造一个循环。您还必须返回此循环!

如果您的语言具有内置阶乘,则可以使用它。我对返回类型并不挑剔,您只需要以人类可以理解的格式返回sumFac应用程序的序列和循环。

编辑:为了帮助您更好地可视化输出,我复制下面的Leaky Nun的内容应该是什么:

[132, 9, 362880, 81369, 403927, 367953, 368772, 51128, 40444, 97, 367920, 368649, 404670, 5810, 40442, 75, 5160, 842, 40346, 775, 10200, 6, 720, 5043, 151, 122, 5, 120, 4, 24, 26, 722, 5044, 169, 363601, 1454]

您只需要在第二次循环即将开始时停止序列!

但这是代码高尔夫球,所以最短的答案以字节为单位!

排行榜

这是一个堆栈片段,用于按语言生成常规排行榜和获胜者概述。



欢迎来到PPCG!顺便说一句,这似乎是一个不错的挑战。
clismique

@ Qwerp-Derp非常感谢!我试图发挥创造力^^

@Zgarb好吧,这就像Leaky Nun的输出一样。申请的顺序,然后应在第二个周期开始之前结束。我将在问题中复制他的输出,以便每个人都可以清楚了解。感谢您指出:)

1
@ 2501硬编码该值是作弊的,但是关于输出格式,您可以使用任何所需的分隔符

Answers:


19

果冻,6个字节

D!SµÐĿ
    ÐĿ  Repeat until the results are no longer unique. Collects all intermediate results.
D           Convert from integer to decimal (list of digits)
 !          Factorial (each digit)
  S         Sum

在线尝试!

除了按照说明进行操作外,我没有其他方法可以缩短它的时间。

眼镜

  • 输入:(132作为命令行参数)
  • 输出: [132, 9, 362880, 81369, 403927, 367953, 368772, 51128, 40444, 97, 367920, 368649, 404670, 5810, 40442, 75, 5160, 842, 40346, 775, 10200, 6, 720, 5043, 151, 122, 5, 120, 4, 24, 26, 722, 5044, 169, 363601, 1454]

我没想到这么短的答案。尼斯:)

4
@Antoine这是果冻:D它总是比我想的要短;)
HyperNeutrino

8
@HyperNeutrino不知何故,丹尼斯会给出一个更短的答案
Leaky Nun

是的,是的。因为丹尼斯。:P
HyperNeutrino

那么...您使用哪种字符编码来为这6个字符提供6个字节?Jelly是否应该使用UTF-8编码,这意味着该程序实际上是9个字节?
LordOfThePigs 17-4-26的

10

Python 2,88字节

import math
f=lambda x,l=[]:l*(x in l)or f(sum(math.factorial(int(i))for i in`x`),l+[x])

在线尝试!


作为python的粉丝,我很高兴有人回答了这个问题,很好:)

9

05AB1E,12个字节

[DˆS!O©¯så#®

在线尝试!

说明

[               # infinite loop
 Dˆ             # add a copy of current value to the global list (initialized as input)
   S            # split current number to digits
    !O          # calculate factorial of each and sum
      ©         # save a copy in register
       ¯så#     # if the current number is in the global list, exit loop
           ®    # retrieve the value from the register for the next iteration
                # implicitly output the global list

简短正确,演奏不错!

以为我可以摆脱,这s是错误的,不错的答案。
魔术章鱼缸

8

Brachylog,17个字节

g:I{tẹḟᵐ+}ᵃ⁾L¬≠Lk

在线尝试!

说明

g:I{     }ᵃ⁾         Accumulate I (a variable) times, with [Input] as initial input:
    t                  Take the last integer
     ẹḟᵐ+              Compute the sum of the factorial of its digits
            L        The result of the accumulation is L
            L­      Not all elements of L are different
               Lk    Output is L minus the last one (which is the start of the loop)

什么I意思
Leaky Nun

1
@LeakyNun这是的参数ᵃ⁾ᵃ³表示“累计3次”。ᵃ⁾表示“累加次数是输入的最后一个元素的次数”,在这种情况下为I。由于I是完全免费的变量,因此它将尝试从0到的值+inf
Fatalize

8

Wolfram语言,62 60 56字节

Most@NestWhileList[Tr[IntegerDigits@#!]&,#,UnsameQ,All]&

Wolfram语言具有如此长的函数名称真是太糟糕了。*叹*

说明:

Most[NestWhileList[Tr[IntegerDigits[#]!]&,#,UnsameQ,All]]&
                      IntegerDigits[#]                     (*Split input into list of digits*)
                                      !                    (*Factorial each element in the list*)
                   Tr[                 ]&                  (*Sum the list together*)
     NestWhileList[                      ,#,UnsameQ,All]   (*Iterate the function over itself, pushing each to a list, until a repeat is detected*)
Most[                                                   ]& (*Remove the last element in the list*)

好答案。我认为这无法改善。
凯利·洛德

1
@KellyLowder谢谢!实际上,通过将阶乘映射到列表,然后将其求和,我实际上可以再节省两个字节Tr
Scott Milner

1
很好用NestWhileList[...,All]
格雷格·马丁

6

JavaScript(ES6),91 89字节

感谢fəˈnɛtɪk节省了2个字节

事实证明,它与其他JS答案非常相似。

f=(n,x=!(a=[n]))=>n?f(n/10|0,x+(F=n=>n?n--*F(n):1)(n%10)):~a.indexOf(x)?a:f(x,!a.push(x))


在阶乘函数中,因为0!= 1,您不应该使用n而不是n> 1吗?
fəˈnɛtɪk

@ fəˈnɛtɪk我不知道我在这里想什么。谢谢!
Arnauld

5

ClojureScript,146 109字节

#(loop[n[%]](let[f(apply +(for[a(str(last n))](apply *(range 1(int a))))](if(some #{f}n)n(recur(conj n f)))))

kes,那是怪兽。有人请帮我打高尔夫球...

感谢您@cliffroot节省多达37个字节!

这是一个匿名函数,要运行该函数,您必须执行以下操作:

(#(...) {arguments})

TIO没有ClojureScript,因此是ClojureScript REPL 的链接

是Clojure程序的链接,该程序打印列表中从0到1000的最后一个元素。

这是输出9999

[9999 1451520 269 363602 1455 265 842 40346 775 10200 6 720 5043 151 122 5 120 4 24 26 722 5044 169 363601 1454]

我强烈怀疑所有的数字最终都必须落在1这个循环上[169 363601 1454]

取消程式码:

(defn fact-cycle [n]
  (loop [nums [n]]
    (let [fact-num
          (let [str-n (str (last nums))]
            (apply +
              (for [a (range (count str-n))]
                (apply *
                  (range 1
                    (inc (int (nth str-n a))))))))]
      (if (some #{fact-num} nums) nums
        (recur
          (conj nums fact-num))))))

解释即将推出!


很长但正确的;)我真的无法帮助您打高尔夫球,对不起^^

内在for可以(for[a s](apply *(range 1(-(int a)47)))),不是吗?
悬崖根

并且这将使其他人摆脱let #(loop[n[%]](let[f(apply +(for[a(str(last n))](apply *(range 1(-(int a)47)))))](if(some #{f}n)n(recur(conj n f)))))
悬崖根

哦,看来您甚至不需要(- ... 47)ClojureScript,就int足够了
悬崖之根

好吧, (inc(int a))应该为ClojureScript和(-(int a)47)Clojure做。
悬崖根

5

Perl 6、64字节

{my@a;$_,{[+] .comb.map:{[*] 2..$_}}...^{$_@a||!@a.push: $_}}

试试吧

展开:

{

  my @a;             # array of values already seen

  $_,                # seed sequence with the input

  {
    [+]              # reduce using &infix:<+>
      .comb          # the digits of $_ (implicit method call)
      .map:          # do the following for each
      {
        [*] 2..$_    # get the factorial of
      }
  }


  ...^               # keep generating values until
                     # (「^」 means throw away the last value when done)

  {
      $_  @a        # is it an elem of @a? (「∈」 is shorter than 「(cont)」)

    ||               # if it's not

      !              # boolean invert so this returns False
        @a.push: $_  # add the tested value to @a
  }
}

上面的每一行都{以隐式参数开始一个新的裸块lambda $_

[*] 2..$_不是[*] 1..$_纯粹将其用作微优化。


4

JavaScript,92个字节

感谢@Shaggy打高尔夫球一个字节,包括
@ @尼尔打高尔夫球两个字节

代码分为单个功能92字节

f=(x,a=[])=>a.includes(x)?a:f(k(x),a,a.push(x))
p=y=>y?y*p(y-1):1
k=n=>n?p(n%10)+k(n/10|0):0

一行代码92字节

f=(x,a=[])=>a.includes(x)?a:f((k=n=>n?(p=y=>y?y*p(y-1):1)(n%10)+k(n/10|0):0)(x),a,a.push(x))

说明

最初仅使用一个参数调用函数,因此使用a = []。

如果x存在于数组中,则返回a a.includes(x)?a:...

否则,将x附加到a并将阶乘和和a传递给函数 (a.push(x),f(k(x),a))

p=y=>y?y*p(y-1):1
k=n=>n?p(n%10)+k(n/10|0):0

执行的阶乘总和不超过最大递归限制。

所有可能端点的列表: 1、2、145、169、871、872、1454、40585、45361、45362、363601

在线尝试!


1
加,我好近!与f=(x,a=[])=>a.includes(x)?a:(a.push(x),f(k(x),a))
Shaggy

你不会写f(k(x),a,a.push(x))吗?另外,我认为您可以写k=n=>n&&以保存另一个字节。
尼尔

4

Haskell80 67字节

g#n|elem n g=g|h<-g++[n]=h#sum[product[1..read[d]]|d<-show n]
([]#)

在线尝试!用法:([]#) 132

编辑:从ØrjanJohansen输入的格式保存了13个字节!


(1)然后测试并追加n而不是s(与ovs的Python答案相同)f=([]#)。(2)切换分支,内联s并使用elem
与Orjan约翰森

换出你++:也。

1
@Canyon这是错误的顺序,它将使最终结果相反。之后,您可以通过添加一个额外的内容并将其更改为来几乎将其修复,但这似乎只是平局。n:=g=[]
与Orjan约翰森

4

Pyth,9个字节

.us.!MjNT
.us.!MjNTQ  implicit Q

.u          explained below
       N      current value
      j T     convert to decimal (list of digits)
   .!M        factorial of each digit
  s           sum

在线尝试!

此答案使用.u(“累积定点。应用,直到找到之前发生的结果。返回所有中间结果。”)




2

R,120字节

o=scan()
repeat {
q=sum(factorial(as.double(el(strsplit(as.character(o[length(o)]), "")))))
if(q%in%o)break
o=c(o,q)
}
o

您可以执行o=scan(),使用el()代替[[1]],并且gamma(n+1)=factorial(n)我相信可以保存一个字节,并且我认为as.numericas.double整数相同,整数也可以保存一个字节,您可以使用toString代替as.character
朱塞佩

@Giuseppe感谢您的输入,已更新。
尼尔

2

Java 9 JSHell,213个字节

n->{Set<Integer>s=new HashSet<>();
return IntStream.iterate(n,i->(""+i).chars()
.map(x->x<50?1:IntStream.rangeClosed(2,x-48)
.reduce(1,(a,b)->a*b)).sum()).boxed()
.takeWhile(x->s.add(x)).collect(Collectors.toList());}

在线尝试!

注意:此解决方案依赖于代码点在48-57范围内的数字的字符串表示形式。适用于ASCII,UTF-8,Latin-1,所有ISO-8859- *字符集,大多数代码页。不适用于EBCDIC。我认为没有人会为此扣分。:)

取消高尔夫:

Function<Integer, List<Integer>> f =        // function from Integer to List of Integer
n -> {
    Set<Integer> s = new HashSet<>();       // memo of values we've seen
    return IntStream.iterate(n,             // iterate over n, f(n), f(f(n)), etc.
    i -> (""+i).chars()                     // the sumFac function; for all chars
        .map(x -> x < 50? 1 :               // give 1 for 0! or 1!
        IntStream.rangeClosed(2, x-48)      // else produce range 2..d 
        .reduce(1,(a,b)->a*b))              // reduction to get the factorial
        .sum())                             // and sum up the factorii!

                                            // now we have a stream of ints
                                            // from applying sumFac repeatedly
        .boxed()                            // box them into Integers (thanks, Java)
        .takeWhile(x->s.add(x))             // and take them while not in the memo
        .collect(Collectors.toList());      // collect them into a list
}

笔记:

  • Set :: add的返回值在这里非常有帮助;返回true如果项目不在集合中,则
  • 当我说“谢谢Java”时,我很讽刺。
  • factorii并不是一个字。我只是编造的

1
我承认这是原创!

@Antoine我承认,Java不是打高尔夫的最佳语言,但这并不是我最近所做的最疯狂的事情。:) codegolf.stackexchange.com/a/117644/794
David Conrad

2

Pyth,22个 11字节

.usm.!sd+Nk

在线尝试!

非常感谢Leaky Nun的回答,这使我了解了.u,并帮助节省了该程序的11个字节。

说明:

.usm.!sd+NkQ | ending Q is implicitly added
             | Implicit: Q = eval(input())
.u         Q | Repeat the function with initial value Q until a previous value is found. Return all intermediate values
  s          | Summation
   m.!sd     | For each character 'd' in the string, convert to integer and take the factorial
        +Nk  | Convert function argument to string

Pyth具有比人们想象的更有用的功能。请参阅我的答案作为参考。
Leaky Nun

@LeakyNun我已重写要使用的答案.u。我想我需要再次浏览一下字符引用,看看那里是否还有其他有用的功能。
K张

您可以使用`N而不是转换为字符串+Nk
Leaky Nun

@LeakyNun N届时将会过时,并且有一个9字节的解决方案...
Egg the Outgolfer

1

公理,231字节

l(a:NNI):List NNI==(r:List NNI:=[];repeat(r:=cons(a rem 10,r);a:=a quo 10;a=0=>break);r)
g(a:NNI):NNI==reduce(+,[factorial(x) for x in l(a)])
h(a:NNI):List NNI==(r:=[a];repeat(a:=g(a);member?(a,r)=>break;r:=cons(a,r));reverse(r))

没有高尔夫功能和一些测试

-- convert one NNI in its list of digits
listify(a:NNI):List NNI==
    r:List NNI:=[]
    repeat
        r:=cons(a rem 10,r)
        a:=     a quo 10
        a=0=>break
    r

-- g(1234)=1!+2!+3!+4!
SumfactorialDigits(a:NNI):NNI==reduce(+,[factorial(x) for x in listify(a)])

ListGenerateFromSumFactorialDigits(a:NNI):List NNI==
    r:=[a]
    repeat
       a:=SumfactorialDigits(a)
       member?(a,r)=>break
       r:=cons(a,r)
    reverse(r)

(9) -> h 132
   (9)
   [132, 9, 362880, 81369, 403927, 367953, 368772, 51128, 40444, 97, 367920,
    368649, 404670, 5810, 40442, 75, 5160, 842, 40346, 775, 10200, 6, 720,
    5043, 151, 122, 5, 120, 4, 24, 26, 722, 5044, 169, 363601, 1454]

1

Java 7,220字节

String c(int n){String r=n+",",c;for(;!r.matches("^"+(c=(n=d(n))+",")+".*|.*,"+c+".*");r+=c);return r;}int d(int n){int s=0;for(String i:(n+"").split(""))s+=f(new Long(i));return s;}long f(long x){return x<2?1:x*f(x-1);}

说明:

String c(int n){                            // Method with integer parameter and String return-type
  String r=n+",",                           //  Result-String (which starts with the input integer + a comma
         c;                                 //  Temp String
  for(;!r.matches(                          //  Loop as long as the result-String doesn't match the following regex:
    "^"+(c=(n=d(n))+",")+".*|.*,"+c+".*");  //    "^i,.*|.*,i,.*" where `i` is the current integer
                                            //   `n=d(n)` calculates the next integer in line
                                            //   `c=(n=d(n))+","` sets the temp String to this integer + a comma
    r+=c                                    //   And append the result-String with this temp String
  );                                        //  End of loop
  return r;                                 //  Return the result-String
}                                           // End of method

int d(int n){                               // Separate method (1) with integer parameter and integer return-type
  int s=0;                                  //  Sum
  for(String i:(n+"").split(""))            //  Loop over the digits of `n`
    s+=f(new Long(i));                      //   And add the factorial of these digits to the sum
                                            //  End of loop (implicit / single-line body)
  return s;                                 //  Return the sum
}                                           // End of separate method (1)

long f(long x){                             // Separate method (2) with long parameter and long return-type (calculates the factorial)
                                            // (NOTE: 2x `long` and the `new Long(i)` is shorter than 2x `int` and `new Integer(i)`, hence long instead of int)
  return x<2?                               //  If `x` is 1:
      1                                     //   return 1
    :                                       //  Else:
      x*f(x-1);                             //   return `x` multiplied by the recursive-call of `x-1`
}                                           // End of method (2)

测试代码:

在这里尝试。

class M{
  String c(int n){String r=n+",",c;for(;!r.matches("^"+(c=(n=d(n))+",")+".*|.*,"+c+".*");r+=c);return r;}int d(int n){int s=0;for(String i:(n+"").split(""))s+=f(new Long(i));return s;}long f(long x){return x<2?1:x*f(x-1);}

  public static void main(String[] a){
    System.out.println(new M().c(132));
  }
}

输出:

132,9,362880,81369,403927,367953,368772,51128,40444,97,367920,368649,404670,5810,40442,75,5160,842,40346,775,10200,6,720,5043,151,122,5,120,4,24,26,722,5044,169,363601,1454,

1

GolfScript,44个字节

~]{..)\;10base{,1\{)*}/}%{+}*.@\+@@?)!}do);`

~                                             eval input
 ]                                            initialization
  {                                   }do     do...
   ..)\;                                          initialization
        10base                                    get digits
              {,1\{)*}/}%                         factorial each
                         {+}*                     sum
                             .@\+@@?)!        while result not found
                                         );   drop last element
                                           `  tostring

在线尝试!

阶乘部分从这里开始


1

C,161字节

f(a){return a?a*f(a-1):1;}
a(l){return l?f(l%10)+a(l/10):0;}
c,t,o;r(i){for(t=o=i;t=a(t),o=a(a(o)),c=t^o;);for(t=i;t^c;printf("%d ",t),c=c|t^o?c:o,t=a(t),o=a(o));}

看到它在线上工作。


1

TI-BASIC,85 79 64 60字节

:Prompt L₁                             //Get input as 1 length list, 4 bytes
:Lbl C                                //create marker for looping, see below, 3 bytes
:int(10fPart(Xseq(10^(~A-1),A,0,log(X //split input into list of digits, 20 bytes
:sum(Ans!→X                           //factorial and sum the list, write to new input, 6 bytes
:If prod(L₁-X                         //Test to see if new element is repeated, see below, 7 bytes
:Then                                 //Part of If statement, 2 bytes
:augment(L₁,{X→L₁                     //Push new input to List 1, 10 bytes
:Goto C                               //Loop back to beginning, 3 bytes
:Else                                 //Part of If statement, 2 bytes
:L₁                                   //Print Answer, 2 bytes

由于这是在图形计算器上运行的,因此内存有限。尝试使用快速循环的数字(例如)进行测试169

更多说明:

:int(10fPart(Xseq(10^(~A-1),A,0,log(X
              seq(10^(~A-1),A,0,log(X //Get a list of powers of 10 for each digit (i.e. 1, 0.1, 0.01, etc.)
             X                        //Multiply by input
       fPart(                         //Remove everything but the decimal
     10                               //Multiply by 10 (move one digit in front of the decimal
:int(                                 //Truncate to an integer

If prod(L₁-X通过从旧列表中减去新元素,然后将列表中的所有元素相乘在一起来工作。如果元素已经在列表中,则乘积将为0,为假值。否则,乘积将为正整数,即真实值。



1

J40 31字节

编辑:使用FrownyFrog的改进保存9个字节。谢谢!

f=.$:@,~`]@.e.~[:+/@:!10#.inv{:

原始代码:

f =。[`($:@,)@。([:-。e。〜)[:+ /!@(“。” 0&“:@ {:)

在这种情况下,我决定为动词定义计算字节数,因为否则它在解释器中不起作用。

说明:

                         ({:)-取得数组的最后一个元素
                               “:@-将其转换为字符串
                          “。”-0-将每个字符转换回整数
                       !@-查找阶乘
                     + /-求和
                   [:-cap(上面有2个衍生动词,我们需要3个分叉)
          (e。〜)-检查结果是否在列表中    
             - -取消上述检查
           [:-上限
        @。-递归所需的议程连词
  ($:@,)-如果结果不在列表中,请将其添加到列表中,然后重复进行
[`-如果结果在列表中,则显示并停止    

在线尝试!


1
([:-.e.~)->(1-e.~)
FrownyFrog


@FrownyFrog谢谢,您的代码要好得多!我在实验的初期尝试了10#.inv,但是后来我写了10&#。inv,它又更长了,所以我拒绝了。感谢您的所有建议!我有很多东西要学:)
Galen Ivanov

@FrownyFrog撤消议程的要求真是太好了,很遗憾我没有看到:)
Galen Ivanov

[:+/!@"."0@":@{:的长度相同,因此不会有任何改善10#.inv。只是不得不放弃()
FrownyFrog

1

Tcl,143字节

proc P {n L\ ""} {proc F n {expr $n?($n)*\[F $n-1]:1}
while {[set n [expr [join [lmap d [split $n ""] {F $d}] +]]] ni $L} {lappend L $n}
set L}

在线尝试!

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.