階乗と決して終わらないサイクル!


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]

サイクルが2回目になりそうなときに、シーケンスを停止する必要があります!

しかし、これはコードゴルフなので、バイト単位の最短回答が勝ちです!

リーダーボード

これは、通常のリーダーボードと言語ごとの勝者の概要の両方を生成するスタックスニペットです。



PPCGへようこそ!これはいい挑戦ですね。
clismique

@ Qwerp-Derpありがとうございます!私は創造的にしようとしました^^

@Zgarbまあ、Leaky Nunの出力とまったく同じです。アプリケーションのシーケンスは、2番目のサイクルの開始直前に終了します。質問の彼の出力をコピーして、誰もが明確に理解できるようにします。それを指摘してくれてありがとう:)

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]

そんなに短い答えを期待していませんでした。ニース:)

4
@アントワーヌそれはゼリーです:Dそれは私がそれがなると思うよりも常に短いです;)
HyperNeutrino

8
@HyperNeutrinoどういうわけかデニスはさらに短い答えが来る
リーキー修道女

どういうわけか、はい。デニスだから。: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は間違っていて、いい答えでした。
魔法のタコUr

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意味ですか?
リーキー修道女

1
@LeakyNunのパラメーターᵃ⁾です。ᵃ³「3回累積する」という意味です。ᵃ⁾は、「入力の最後の要素と同じ回数だけ累積する」という意味ですI。以来I、完全に自由変数があり、それから、それに対する値をしようと0します+inf
致命的

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ありがとう!階乗をリストにマッピングし、それをで合計することで、実際にさらに2バイトを節約できましたTr
スコットミルナー

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> 1ではなくnを使用できませんか?
-fəˈnɛtɪk

@ fəˈnɛtɪk私はここで何を考えていたのか分かりません。ありがとうございました!
アーナルド

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

Yikes、それは怪物です。誰かこのゴルフを手伝ってください...

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

未ゴルフコード:

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

上記のすべての行{は、の暗黙的なパラメーターで新しいベアブロックラムダを開始します$_

単にマイクロ最適化として使用する[*] 2..$_代わりに使用しました[*] 1..$_


4

JavaScript、92バイト

インクルードで1バイトをゴルフしてくれてありがとう@Shaggy
くれてありがとう@Shaggy 2バイトをオフにゴルフしてくれてありがとう@Neil

個々の機能に分離されたコード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

1行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))

説明

最初に1つの引数だけで関数を呼び出します。したがって、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))
シャギー

書けない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)(ovsのPythonの回答と同じ)のn代わりに、テストして追加します。(2)ブランチを切り替えて、インラインにし、を使用します。sf=([]#)selem
Ørjanヨハンセン

またあなたの++ために切り替えます:

1
@Canyonそのための順序は間違っています。最終結果が逆になります。あなたは、することができ、ほとんどの余分を付加することで、後でそれを修正n:し、変更すること=g=[]、唯一のネクタイのようです。
Ørjanヨハンセン

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入力をありがとう、更新しました。
ニール

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
デビッドコンラッド

2

Pyth、22 11バイト

.usm.!sd+Nk

オンラインでお試しください!

Leaky Nun's answerに多くの功績があり、私を紹介し.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には、想像以上の便利な機能があります。参考として私の答えをご覧ください。
リーキー修道女

@LeakyNun使用する回答を書き直しました.u。文字参照をもう一度調べて、他の便利な関数があるかどうかを確認する必要があると思います。
Kチャン

を使用`Nして、の代わりに文字列に変換できます+Nk
リーキー修道女

@LeakyNun N当時は廃止され、9バイトのソリューションが登場します...
エリックアウトゴルファー

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

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

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と書いたのでそれよりも長いので拒否しました。すべてのご提案ありがとうございます!学ぶべきことがたくさんあります:)
ガレンイワノフ

@FrownyFrogアジェンダのケースを逆にするのはとても良いです、私はそれを見なかったことを後悔しています:)
ガレンイワノフ

[:+/!@"."0@":@{:は同じ長さなので、による改善はありません10#.inv。ちょうどドロップしなければなりませんでした()
-FrownyFrog

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.