階乗の合計


25

課題は、数値の階乗の桁合計を計算することです。


Input: 10
Output: 27

10!= 10×9×...×3×2×1 = 3628800、および数字10の数字の合計!3 + 6 + 2 + 8 + 8 + 0 + 0 = 27

入力は0より大きい整数であることが期待できます。出力はどのタイプでもかまいませんが、答えはコーディング言語の標準ベースである必要があります。


テストケース:

10    27
19    45
469   4140
985   10053

注意一部の言語では、32ビット整数を超える大きな数値をサポートできません。これらの言語では、大きな階乗を計算することは期待されません。

マーティン・エンダーのおかげでここにOEISリンク


これはなので、文字の中で最も短いコードが勝ちです!


予想される最大入力数は?Rの32ビット整数では、この課題を正確に解決することはできませんn>21
-Billywob

1
@Billywob Rの場合は、20に進むだけです。これを反映するように質問を編集します。
ジョージ

回答:





7

C ++ 11、58バイト

入力を変更する名前のないラムダとして:

[](int&n){int i=n;while(--n)i*=n;do n+=i%10;while(i/=10);}

私のC ++コードがCコードよりも短いまれなケースの1つ。

より大きなケースをサポートしたい場合は、C ++ 14に切り替えて使用します。

[](auto&n){auto i=n;while(--n)i*=n;do n+=i%10;while(i/=10);}

呼び出し引数にull接尾辞を付けます。

使用法:

auto f=
[](int&n){int i=n;while(--n)i*=n;do n+=i%10;while(i/=10);}
;

main() {
  int n=10;
  f(n);
  printf("%d\n",n);
}

7

ルビー、63 61 53 38バイト

マナトワークによる新しいアプローチ:

->n{eval"#{(1..n).reduce:*}".chars*?+}

古い:

->n{(1..n).reduce(:*).to_s.chars.map(&:hex).reduce:+}
  • Martin Enderのおかげで-3バイト
  • GBのおかげで-5バイト

1
古い退屈なeval方法:->n{eval"#{(1..n).reduce:*}".chars*?+}
マナトワーク

6

Pyth、7 6バイト

バイトを節約してくれた@Kadeに感謝

sj.!QT

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

Pythを使用するのはこれが初めてなので、私の答えはかなりの量になると確信しています。

説明:

s Sum
  j the digits of
    .! the factorial of
      Q the input
    T in base 10

1
10変数に代入されTますが、このことができますので、sj.!QT:)
カーデ

OK、ありがとう!追加します
-BookOwl

いいね!ssM`.!また、6バイトでジョブを実行します。
hakr14

5

Haskell、41 40バイト

f x=sum$read.pure<$>(show$product[1..x])

使用例:f 985-> 10053

1to からリストを作成しx、リスト要素の積を計算し、それを文字列表現に変換し、各文字を数字に変換して合計します。

編集:@Angsはバイトを保存しました。ありがとう!


f x=sum$read.pure<$>(show$product[1..x])バイトを保存
-Angs

5

Python、54バイト

f=lambda n,r=1:n and f(n-1,r*n)or sum(map(int,str(r)))

repl.it


私はちょうど見えます。この若干悪化したバージョンを思い付いた方法、それは別の答えであるためにあまりにも似ています。ブラボー
osuka_

5

R、58 53バイト

編集:@ジョナサン・キャロルのおかげで1バイト、@ Micky Tのおかげで1バイト節約

sum(as.double(el(strsplit(c(prod(1:scan()),""),""))))

残念ながら、32ビット整数では、これはでのみ機能しn < 22ます。stdinから入力を受け取り、stdoutに出力します。

より高いレベルの精度が必要な場合は、次のような外部ライブラリを使用する必要がありますRmpfr

sum(as.numeric(el(strsplit(paste(factorial(Rmpfr::mpfr(scan()))),""))))

1
私はあなたが行ったように、その後、まったく同じ答えに到達した上で1バイトのゲインたc(x,"")対をpaste(x)sum(as.integer(el(strsplit(c(factorial(scan()),""),""))))。階乗の結果を文字に強制し、strsplitそれを2番目のリストとして返します。したがって、elまだ機能し、最初のリスト要素を抽出します。
ジョナサンキャロル

2
どうprod(1:scan())
MickyT

1
また、as.double 十分である必要があります
MickyT

@MickyTありがとう!更新しました。
ビリーウォブ

strtoi短い代替品として機能するas.doubleと思います。
ジュゼッペ

4

ピップ、8バイト

$+$*++,a

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

説明

      ,a    # range
    ++      # increment
  $*        # fold multiplication
$+          # fold sum

申し訳ありませんが、実際にあなたの前に05AB1Eの回答を投稿できました;)。
魔法のタコUr

2
@carusocomputing:へへ。新しい言語を調べる機会を得ました:)
エミグナ

1
あなたは、私以外で、ポリグロットコード以外のゴルフの答えにPipを使用した最初の人だと思います。:D
DLosc 16



3

Java 7、148バイト

int s=1,ret=0;while(i>1){s=s*i; i--;}String y=String.valueOf(s);for(int j=0;j<y.length();j++){ret+=Integer.parseInt(y.substring(j,j+1));}return ret;

@EyalLev質問には制限はありません。9,223,372,036,854,775,807よりも大きい階乗を処理するために、長い間どのように期待していますか?
jacksonecac

3

ルビー、63 60 53 51バイト

->n{a=0;f=(1..n).reduce:*;f.times{a+=f%10;f/=10};a}

ゴルフの手助けをしてくれたマーティンに感謝します。


3

Pushy、4バイト

fsS#

コマンドラインで入力を行います$ pushy facsum.pshy 5。内訳は次のとおりです。

f      % Factorial of input
 s     % Split into digits
  S    % Push sum of stack
   #   % Output

3

オクターブ、30バイト

@(n)sum(num2str(prod(1:n))-48)

リストの積をとることにより階乗を計算します[1 2 ... n]。それを文字列に変換し、48すべての要素から減算します(ASCIIコード0)。最後にそれを要約します:)


3

bash(seq、bc、fold、jq)、34 33バイト

確かに最もエレガントではありませんが、挑戦のために

seq -s\* $1|bc|fold -1|jq -s add

fold -1バイトを保存します。
デジタル外傷

@DigitalTrauma修正済み!ありがとう
アダム

3

C、58バイト

これは完璧ではありません。aは開始時に-1でなければならないため、機能するのは1つだけです。1つの関数で2つの再帰関数を使用するという考え方です。最初に思ったほど簡単ではありませんでした。

a=-1;k(i){a=a<0?i-1:a;return a?k(i*a--):i?i%10+k(i/10):0;}

使用法とわかりやすい形式:

a = -1;
k(i){
   a = a<0 ? i-1 : a;
   return a ? k(i*a--) : i? i%10+k(i/10) :0;
}

main() {
   printf("%d\n",k(10));
}

編集:私はこの関数を複数回使用できるmetodeを見つけましたが、長さは62バイトです。

a,b;k(i){a=b?a:i+(--b);return a?k(i*a--):i?i%10+k(i/10):++b;}

いいアイデアですが、a(b(10))のように、ある関数を使用して階乗を返し、別の関数を使用して桁合計を計算する方が短くならない理由はよくわかりません。「戻る」という言葉は長すぎますか?
JollyJoker

戻りは多くを食べる。もちろんやってみます。たぶん誰かが、少なくとも私はその仕事を得ることができなかったそれを行うことができます
teksturi

1
2つの引数を受け入れて数バイトを保存できます:codegolf.stackexchange.com/a/153132/77415-user84207 18
1

3

Perl 6、21バイト

{[+] [*](2..$_).comb}

拡張:

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

  [+]           # reduce the following with 「&infix:<+>」

    [*](        # reduce with 「&infix:<*>」
      2 .. $_   # a Range that include the numbers from 2 to the input (inclusive)
    ).comb      # split the product into digits
}

おめでとうございます、いいえと答えました。101010!
ルドルフジェリン

@RudolfL.Jelínekそれの上の何もない、StackOverflowの、そしてMeta.StackExchange I AMユーザー数1337
ブラッド・ギルバートがb2gills

3

Cubix、33 32バイト

u*.$s.!(.01I^<W%NW!;<,;;q+p@Opus

ネット形式:

      u * .
      $ s .
      ! ( .
0 1 I ^ < W % N W ! ; <
, ; ; q + p @ O p u s .
. . . . . . . . . . . .
      . . .
      . . .
      . . .

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

ノート

  • 170以上の入力で動作します。より高い入力は、その階乗がInfinity数値を生成するため、無限ループになります(技術的には、ウィンドウオブジェクトの書き込み不可、列挙不可能、構成不可能なプロパティです)。
  • 2 53(= 9 007 199 254 740 992)を超える数値はJavaScriptに正確に保存できないため、入力19以上では精度が失われます。

説明

このプログラムは2つのループで構成されています。最初は入力の階乗を計算し、もう一方は結果を数字に分割し、それらを加算します。その後、合計が印刷され、プログラムが終了します。

開始

まず、スタックを準備する必要があります。その部分では、最初の3つの指示を使用します。IPは、東を指す4行目から始まります。スタックは空です。

      . . .
      . . .
      . . .
0 1 I . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
      . . .
      . . .
      . . .

スタックの一番下に合計を保持するため、スタックの一番下に0保存して合計にすることから始める必要があります。次に1、入力を最初にその数で乗算するため、をプッシュする必要があります。これがゼロの場合、階乗も常にゼロになります。最後に、入力を整数として読み取ります。

これで、スタックが[0, 1, input]あり、IPは4番目の行、4番目の列にあり、東を指します。

階乗ループ

これは、スタックの上位2つの要素(前のループと入力-nの結果)を乗算し、入力をデクリメントする単純なループです。入力が0に達すると中断します。$命令はIPをスキップさせますu-ループはキューブの次の部分で、IPは4行4列目から始まります。

      u * .
      $ s .
      ! ( .
. . . ^ < . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
      . . .
      . . .
      . . .

^キャラクターのために、IPはすぐに北へ移動し始めます。次に、uIPが向きを変え、1つ右に移動します。下部には別の矢印があります:<IPをに向け^ます。スタックはから始まります。[previousresult, input-n]ここnで、は反復回数です。ループ内で次の文字が実行されます。

*s(
*   # Multiply the top two items
    #   Stack: [previousresult, input-n, newresult]
 s  # Swap the top two items
    #   Stack: [previousresult, newresult, input-n]
  ( # Decrement the top item
    #   Stack: [previousresult, newresult, input-n-1]

次に、スタックの最上部(入力の減少)が命令0によってチェックされ、チェックされている!場合0u文字はスキップされます。

数字を合計する

IPはキューブを包み込み、最終的に4行目の最後の文字で終わり、最初は西を指します。次のループは、ほとんどすべての残りの文字で構成されています。

      . . .
      . . .
      . . .
. . . . . W % N W ! ; <
, ; ; q + p @ O p u s .
. . . . . . . . . . . .
      . . .
      . . .
      . . .

ループは、最初にスタックから最上位のアイテム(10または0)を削除し、次に階乗の結果の残りをチェックします。それがに減少した場合0、スタックの一番下(合計)が出力され、プログラムが停止します。それ以外の場合、次の命令が実行されます(スタックはとして開始します[oldsum, ..., factorial])。

N%p+q;;,s;
N          # Push 10
           #   Stack: [oldsum, ..., factorial, 10]
 %         # Push factorial % 10
           #   Stack: [oldsum, ..., factorial, 10, factorial % 10]
  p        # Take the sum to the top
           #   Stack: [..., factorial, 10, factorial % 10, oldsum]
   +       # Add top items together
           #   Stack: [..., factorial, 10, factorial % 10, oldsum, newsum]
    q      # Send that to the bottom
           #   Stack: [newsum, ..., factorial, 10, factorial % 10, oldsum]
     ;;    # Delete top two items
           #   Stack: [newsum, ..., factorial, 10]
       ,   # Integer divide top two items
           #   Stack: [newsum, ..., factorial, 10, factorial/10]
        s; # Delete the second item
           #   Stack: [newsum, ..., factorial, factorial/10]

そして、ループfactorial/10は0に等しくなるまで再び開始されます。


3

C、47バイト

f(n,a){return n?f(n-1,a*n):a?a%10+f(0,a/10):0;}

使用法:

f(n,a){return n?f(n-1,a*n):a?a%10+f(0,a/10):0;}
main() {
  printf("answer: %d\n",f(10,1));
}


2

バッチ、112バイト

@set/af=1,t=0
@for /l %%i in (1,1,%1)do @set/af*=%%i
:g
@set/at+=f%%10,f/=10
@if %f% gtr 0 goto g
@echo %t%

set/a変数の現在の値に対して便利に機能するため、通常はループ内で機能します。Batchの整数型の制限により、最大12までしか機能しないため、理論的には次のことを想定してバイトを節約できますf<1e9

@set/af=1,t=0
@for /l %%i in (1,1,%1)do @set/af*=%%i
@for /l %%i in (1,1,9)do @set/at+=f%%10,f/=10
@echo %t%

しかし、その方法は狂気にあります...その場合、リストをハードコーディングすることもできます(97バイト):

@call:l %1 1 1 2 6 6 3 9 9 9 27 27 36 27
@exit/b
:l
@for /l %%i in (1,1,%1)do @shift
@echo %2

2

JavaScript(ES6)、50バイト

f=(n,m=1,t=0)=>n?f(n-1,n*m):m?f(n,m/10|0,t+m%10):t

n=22浮動小数点精度の制限のためにのみ機能します。


2

Befunge 9356の 54バイト

保存された2バイトは、引用符の代わりにgetを使用します。これにより、上の2行を1行分ずらして、不要な空白を減らしました。

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

&#:<_v#:-1
: \*$<:_^#
g::v>91+%+00
_v#<^p00</+19
@>$$.

説明:

&#:<                Gets an integer input (n), and reverses flow direction
&#:< _v#:-1         Pushes n through 0 onto the stack (descending order)

:  \*$<:_^#         Throws the 0 away and multiplies all the remaining numbers together

(reorganized to better show program flow):
vp00< /+19 _v#<    Stores the factorial at cell (0, 0). Pushes 3 of whatever's in
> 91+%+ 00g ::^    cell (0, 0). Pops a, and stores a / 10 at (0, 0),
                   and adds a % 10 to the sum.

@>$$.              Simply discards 2 unneeded 0s and prints the sum.

あなたは正しいです。私は新しいバージョンに取り組んでいます。参考までに、私はquickster.comを使用しています。なぜなら、スタックに#が1つしかない場合、他の人が「正しく処理しなかった」からです。
MildlyMilquetoast

ありがとう!おそらくputメソッドが原因で、このコードはBefunge-98バージョンでのみ正常に動作するようです。
MildlyMilquetoast

48バイトも0を正しく処理する
ジョーキング

2

JavascriptをES6 - 61の 54のバイト

n=>eval(`for(j of''+(a=_=>!_||_*a(~-_))(n,t=0))t-=-j`)

編集: 7バイトを削ってくれたHediとETHproductionsに感謝します。そのt-=-jトリックを覚えておく必要があります。


1
いい答えだ!さまざまな方法で数バイトを保存できますn=>{a=_=>!_||_*a(~-_);t=0;for(j of''+a(n))t-=-j;return t}
。– ETHproductions

@ETHproductions evalでさらにいくつかのバイトを保存できます。– n=>eval(`for(j of''+(a=_=>!_||_*a(~-_))(n,t=0))t-=-j`)
Hedi

@Hedi私が知っている、私は一度に一歩ずつ
進んでいた:

2

AHK、60バイト

a=1
Loop,%1%
a*=A_Index
Loop,Parse,a
b+=A_LoopField
Send,%b%

AutoHotkeyには組み込みの階乗関数がなく、ループ関数には組み込み変数の長い名前があります。最初のループは階乗で、2番目のループは数字を加算します。


2

J、12 11バイト

コールのおかげで1バイト節約できました!

1#.10#.inv!

これは単に、引数の階乗()の1#.数字(をinv#.とする基底変換の逆を使用)に合計()を適用します。10!

テストケース

注:最後の2つのテストケースは、末尾がでマークされているbigint xです。

   f=:10#.inv!
   (,. f"0) 10 19 469x 985x
 10    27
 19    45
469  4140
985 10053

あなたは"."0":数字を取得するために使用することができます
ボルチェビュシエール

11バイト:1#.,.&.":@!小さい場合にも拡張精度が必要です(理由はわかりません)。また11バイト:1#.10#.inv!
コール


1

C、63 60バイト

do...whileループ用の-3バイト。

i;f(n){i=n;while(--n)i*=n;do n+=i%10;while(i/=10);return n;}

ゴルフをしないと使用法:

i;
f(n){
 i=n;
 while(--n)
  i*=n;
 do
  n+=i%10;
 while(i/=10);
 return n;
}

main() {
 printf("%d\n",f(10));
}

intデフォルトでf(n)を定義していますか?
ムクルクマール

@MukulKumarこれはCの標準であり、型がない場合intは想定されます。
カールナップ16年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.