계승과 끝없는 사이클!


33

아시다시피, 양의 정수의 계승은와 n같거나 작은 모든 양의 정수의 곱입니다 n.

예를 들면 :

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

우리는 이제 다음과 같이 관련이없는 이름으로 특별한 연산을 정의 할 것이다 sumFac:

양의 정수 감안할 때 n, sumFac(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에 오신 것을 환영합니다! 좋은 도전 인 것 같습니다, BTW.
clismique

@ Qwerp-Derp 대단히 감사합니다! 창의력을 발휘하려고했습니다 ^^

@ Zgarb 글쎄, Leaky Nun의 출력과 정확히 같습니다. 적용 순서는 두 번째 사이클이 시작되기 직전에 종료된다. 나는 모든 사람이 명확한 이해를 가질 수 있도록 질문에 그의 결과를 복사 할 것입니다. 지적 해 주셔서 감사합니다 :)

1
@ 2501 하드 코딩 값이 부정 행위이지만 출력 형식과 관련하여 원하는 모든 구분 기호를 사용할 수 있습니다.

답변:


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]

나는 그렇게 짧은 대답을 기대하지 않았다. Nice :)

4
@Antoine 그것은 젤리입니다 : D 그것은 항상 그것이 생각할 것보다 짧습니다;)
HyperNeutrino

8
@HyperNeutrino 어쨌든 데니스는 더 짧은 답변을 제공합니다
Leaky Nun

그렇습니다. 데니스 때문이야 : P
HyperNeutrino

그렇다면 ...이 6 문자에 대해 6 바이트를 만들기 위해 어떤 문자 인코딩을 사용합니까? Jelly가 UTF-8로 인코딩되어 있지 않습니까?이 프로그램은 실제로 9 바이트입니까?
LordOfThePigs


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. 잘못되었습니다.
Magic Octopus Urn

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 Language의 기능 이름이 너무 길다는 것은 정말 나쁜 일입니다. *한숨*

설명:

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*)

좋은 대답입니다. 나는 이것이 향상 될 수 있다고 생각하지 않습니다.
Kelly Lowder

1
@KellyLowder 감사합니다! 실제로 계승을 목록에 매핑 한 다음로 합하여 두 바이트를 더 절약 할 수있었습니다 Tr.
Scott Milner

1
의 좋은 사용 NestWhileList[...,All]!
Greg Martin

6

자바 스크립트 (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> 1 대신 n을 사용할 수 없어야합니다.
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)))))

이케 스, 그것은 괴물이다. 누군가 골프를 도와주세요 ...

@cliffroot무려 37 바이트를 줄여 주셔서 감사 합니다!

이것은 익명 함수입니다. 함수를 실행하려면 다음을 수행해야합니다.

(#(...) {arguments})

TIO에는 ClojureScript가 없으므로 ClojureScript REPL에 대한 링크 가 있습니다.

다음 은 목록의 마지막 요소를 0에서 1000까지 인쇄하는 Clojure 프로그램에 대한 링크 입니다.

출력은 다음과 같습니다 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].

Ungolfed 코드 :

(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))))수 있습니까?
cliffroot

그리고 이것은 다른 사람을 제거 할 수 있습니다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)))))
cliffroot

오, (- ... 47)ClojureScript 에서도 필요하지 않은 것 같습니다. 이것으로 int충분합니다
cliffroot

물론, (inc(int a))ClojureScript과해야 (-(int a)47)Clojure에 대한.
cliffroot

5

펄 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
  }
}

위의 모든 줄은 {의 암시 적 매개 변수로 새로운 베어 블록 람다를 시작합니다 $_.

나는 순전히 마이크로 최적화 [*] 2..$_대신에 사용 했습니다 [*] 1..$_.


4

자바 스크립트, 92 바이트

1 바이트를 골프로 해주셔서 감사합니다 @Shaggy
2 바이트를 골프로 해주셔서 감사합니다 @ 닐

개별 기능으로 분리 된 코드 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&&다른 바이트를 저장하기 위해 쓸 수 있다고 생각합니다 .
Neil

4

하스켈 , 80 67 바이트

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

온라인으로 사용해보십시오! 용법:([]#) 132

편집 : Ørjan Johansen에서 일반으로 13 바이트를 저장했습니다!


(1) n대신 s(ovs의 Python 답변과 동일 ) 테스트하고 추가 한 다음 f=([]#). (2) 분기를 인라인으로 전환하고을 s사용하십시오 elem.
Ørjan Johansen

당신의 밖으로 스위치 ++를 들어 :도.

1
@Canyon 그것은 잘못된 순서이므로 최종 결과가 반전됩니다. 당신은 할 수 있습니다 거의 추가를 앞에 붙이는, 나중에 그것을 수정 n:및 변경 =g=[]있지만, 단지 타이 것으로 보인다.
Ørjan Johansen

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.numeric과 동일 as.double또한 바이트를 저장 정수에 대해, 당신은 사용할 수 있습니다 toString대신 as.character.
Giuseppe

@Giuseppe 입력에 감사드립니다.
Neil

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
나는 이것이 원본임을 인정한다! Nice job :)

@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 Zhang

`N대신 문자열로 변환하는 데 사용할 수 있습니다 +Nk.
Leaky Nun

@LeakyNun N그때 쓸모없고 9 바이트 솔루션이 온다 ...
Outgolfer Erik

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

자바 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

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

그래프 계산기에서 실행되므로 RAM이 제한되어 있습니다. 와 같이 빠르게 반복되는 숫자로 테스트 해보십시오 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이전 목록에서 새 요소를 빼고 목록의 모든 요소를 ​​곱하여 작동합니다. 요소가 이미 목록에 있으면 제품은 0false 값입니다. 그렇지 않으면 곱은 양의 정수, 진실한 값이됩니다.



1

J , 40 31 바이트

편집 : FrownyFrog의 개선 사항을 사용하여 9 바이트를 절약했습니다. 감사!

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

원본 코드 :

f =. [`($ : @,) @. ([:-. e. ~) [: + /! @ ( "."0 & ": @ {:)

이 경우 동사 정의에 대한 바이트 수를 계산하기로 결정했습니다. 그렇지 않으면 인터프리터에서 작동하지 않기 때문입니다.

설명:

                         ({:)-배열의 마지막 요소를 취합니다
                               ": @-문자열로 변환
                          "."0-각 문자를 정수로 다시 변환
                       ! @-계승을 찾습니다
                     + /-합계
                   [:-모자
          (e. ~)-결과가 목록에 있는지 확인    
             -. -위의 확인을 무효화
           [:-캡
        @. -회귀에 필요한 의제 결합
  ($ : @,)-결과가 목록에 없으면 목록에 추가하고 반복하십시오.
[`-결과가 목록에 있으면 표시하고 중지하십시오.    

온라인으로 사용해보십시오!


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


@FrownyFrog 감사합니다. 코드가 훨씬 좋습니다! 실험하는 동안 10 # .inv를 일찍 시도했지만 10 & #. inv라고 쓰고 더 길었으므로 거부했습니다. 모든 제안에 감사드립니다! 나는 배울 것이 많다 :)
Galen Ivanov

@FrownyFrog 의제에 대한 사례를 뒤집는 것은 너무 좋습니다, 나는 그것을 보지 못한 것을 후회합니다 :)
Galen Ivanov

[:+/!@"."0@":@{:길이는 같으므로으로 개선되지 않습니다 10#.inv. 그냥 떨어 뜨렸다 ().
FrownyFrog

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.