Jumlah digit faktorial

25

Tantangannya adalah menghitung jumlah digit faktorial suatu angka.


Contoh

Input: 10
Output: 27

10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800, dan jumlah digit dalam angka 10! adalah 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27

Anda dapat mengharapkan input menjadi bilangan bulat di atas 0. Output dapat berupa jenis apa pun, tetapi jawabannya harus dalam basis standar bahasa pengkodean.


Kasus uji:

10    27
19    45
469   4140
985   10053

NB Beberapa bahasa tidak dapat mendukung angka besar di atas bilangan bulat 32-bit; untuk bahasa-bahasa itu Anda tidak akan diharapkan menghitung faktorial besar.

Tautan OEIS di sini berkat Martin Ender


Ini adalah , jadi kode terpendek dalam karakter menang!

George
sumber
Berapa jumlah input maksimum yang diharapkan? Dengan bilangan bulat 32-bit di R, tantangan ini tidak dapat dipecahkan secara akurat sebelumnyan>21
Billywob
1
@Billywob Untuk R maka Anda hanya perlu pergi ke 20. Saya akan mengedit pertanyaan untuk mencerminkan ini
george

Jawaban:

11

Jelly , 3 byte

!DS

Cobalah online!

Lakukan apa yang Anda harapkan:

!    Factorial.
 D   Decimal digits.
  S  Sum.
Martin Ender
sumber
8

Mathematica, 21 byte

Tr@IntegerDigits[#!]&
Martin Ender
sumber
4
datang ke sini untuk mengetikkan karakter yang tepat ini.
Michael Stern
Kenapa [#!]dan tidak @#!? (Mathematica noob)
Cyoce
1
@Cyoce karena @memiliki prioritas lebih tinggi daripada !.
Martin Ender
7

C ++ 11, 58 byte

Sebagai lambda tanpa nama yang memodifikasi inputnya:

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

Salah satu kasus yang jarang terjadi ketika saya C ++ kode lebih pendek dari kode C .

Jika Anda ingin mendukung kasus yang lebih besar, alihkan ke C ++ 14 dan gunakan:

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

dan berikan argumen panggilan dengan ullakhiran.

Pemakaian:

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);
}
Karl Napf
sumber
7

Ruby, 63 61 53 38 byte

Pendekatan baru berkat manatwork:

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

Tua:

->n{(1..n).reduce(:*).to_s.chars.map(&:hex).reduce:+}
  • -3 byte terima kasih kepada Martin Ender
  • -5 byte berkat GB
TuxCrafting
sumber
1
Lama membosankan evalcara: ->n{eval"#{(1..n).reduce:*}".chars*?+}.
manatwork
6

Pyth, 7 6 byte

Terima kasih kepada @Kade karena telah menyelamatkan saya satu byte

sj.!QT

Cobalah online!

Ini adalah pertama kalinya saya menggunakan Pyth, jadi saya yakin bahwa jawaban saya bisa sedikit golf.

Penjelasan:

s Sum
  j the digits of
    .! the factorial of
      Q the input
    T in base 10
BookOwl
sumber
1
10ditugaskan ke variabel T, sehingga Anda dapat membuat ini sj.!QT:)
Kade
Ok terima kasih! Saya akan menambahkannya
BookOwl
Bagus! ssM`.!melakukan pekerjaan juga, juga dalam 6 byte.
hakr14
5

Haskell, 41 40 byte

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

Contoh penggunaan: f 985-> 10053.

Buat daftar dari 1hingga x, hitung produk elemen daftar, ubah menjadi representasi stringnya, ubah setiap karakter menjadi angka dan jumlahkan.

Sunting: @Angs menyimpan satu byte. Terima kasih!

nimi
sumber
f x=sum$read.pure<$>(show$product[1..x])menghemat satu byte
Angs
5

Python, 54 byte

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

repl.it

Jonathan Allan
sumber
Aku hanya datang dengan versi yang sedikit lebih buruk dari ini yang terlihat seperti terlalu mirip untuk itu menjadi jawaban yang terpisah. Bravo
osuka_
5

R, 58 53 byte

Sunting: Disimpan satu byte berkat @Jonathan Carroll dan pasangan berkat @Micky T

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

Sayangnya, dengan bilangan bulat 32-bit, ini hanya berfungsi untuk n < 22. Membawa input dari stdin dan output ke stdout.

Jika seseorang menginginkan tingkat presisi yang lebih tinggi, ia harus menggunakan beberapa pustaka eksternal seperti Rmpfr:

sum(as.numeric(el(strsplit(paste(factorial(Rmpfr::mpfr(scan()))),""))))
Billywob
sumber
1
Aku mencapai jawaban yang sama persis seperti yang Anda lakukan, kemudian menemukan keuntungan 1-byte pada c(x,"")vs paste(x): sum(as.integer(el(strsplit(c(factorial(scan()),""),"")))). Memaksa hasil faktorial ke karakter dan strsplitmengembalikannya sebagai daftar kedua, jadi elmasih berfungsi dan mengekstrak elemen daftar pertama.
Jonathan Carroll
2
bagaimana prod(1:scan())?
MickyT
1
juga as.double sudah cukup
MickyT
@MickyT Terima kasih! Diperbarui.
Billywob
strtoiberfungsi sebagai pengganti yang lebih pendek as.double, saya pikir.
Giuseppe
4

Pip , 8 byte

$+$*++,a

Cobalah online!

Penjelasan

      ,a    # range
    ++      # increment
  $*        # fold multiplication
$+          # fold sum
Emigna
sumber
Maaf, sebenarnya saya berhasil mengirim jawaban 05AB1E sebelum Anda;).
Magic Gurita Guci
2
@carusocomputing: Hehe. Dapatkan saya kesempatan untuk melihat ke dalam bahasa baru :)
Emigna
1
Saya pikir Anda yang pertama selain saya yang menggunakan Pip untuk jawaban golf kode non-polyglot. : D
DLosc
4

CJam , 8 byte

rim!Ab:+

Cobalah online!

Penjelasan

r   e# Read input.
i   e# Convert to integer.
m!  e# Take factorial.
Ab  e# Get decimal digits.
:+  e# Sum.
Martin Ender
sumber
3

Brachylog , 5 byte

$!@e+

Cobalah online!

Penjelasan

Pada dasarnya algoritma yang dijelaskan:

$!       Take the factorial of the Input
  @e     Take the elements of this factorial (i.e. its digits)
    +    Output is the sum of those elements
Fatalisasi
sumber
3

Java 7, 148 byte

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;
jacksonecac
sumber
@EyalLev Tidak ada batasan yang ditentukan dalam pertanyaan. Bagaimana Anda berharap lama untuk menangani faktorial yang setara dengan lebih besar dari 9.223.372.036.854.775.807?
jacksonecac
3

Ruby, 63 60 53 51 byte

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

Terima kasih kepada Martin untuk bantuan bermain golf.

GB
sumber
3

Pushy , 4 byte

fsS#

Memberikan masukan pada baris perintah: $ pushy facsum.pshy 5. Berikut rinciannya:

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

Oktaf, 30 byte

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

Hitung faktorial dengan mengambil produk dari daftar [1 2 ... n]. Mengubahnya menjadi string dan mengurangi 48dari semua elemen (kode ASCII untuk 0). Akhirnya meringkasnya :)

Stewie Griffin
sumber
3

bash (seq, bc, lipat, jq), 34 33 byte

Tentunya bukan yang paling elegan tetapi untuk tantangan

seq -s\* $1|bc|fold -1|jq -s add
Adam
sumber
fold -1menghemat satu byte.
Digital Trauma
@DigitalTrauma dikoreksi! terima kasih
Adam
3

C, 58 byte

Ini tidak sempurna. Hanya yang berfungsi karena harus -1 di awal. Idenya adalah menggunakan dua fungsi rekursif dalam satu fungsi. Itu tidak semudah yang saya pikirkan.

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

Format penggunaan dan dimengerti:

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

Sunting: Saya menemukan metode yang memungkinkan menggunakan fungsi ini beberapa waktu tetapi kemudian panjangnya adalah 62 byte.

a,b;k(i){a=b?a:i+(--b);return a?k(i*a--):i?i%10+k(i/10):++b;}
teksturi
sumber
Ide bagus, tapi saya tidak mengerti mengapa tidak akan lebih pendek untuk menggunakan satu fungsi untuk mengembalikan faktorial dan yang lain untuk menghitung jumlah digit, seperti (b (10)). Apakah kata "kembali" terlalu lama untuk berhasil?
JollyJoker
Makan kembali banyak. Saya mencobanya tentu saja. Mungkin seseorang bisa melakukannya setidaknya saya tidak bisa mendapatkan pekerjaan itu
teksturi
1
Anda bisa menerima dua argumen untuk menghemat beberapa byte: codegolf.stackexchange.com/a/153132/77415
user84207
3

Perl 6 , 21 byte

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

Diperluas:

{  # 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
}
Brad Gilbert b2gills
sumber
Selamat, Anda mendapat jawaban tidak. 101010!
RudolfJelin
@ RudolfL.Jelínek Bukan apa-apa, di StackOverflow , dan Meta.StackExchange Saya nomor pengguna 1337
Brad Gilbert b2gills
3

Cubix, 33 32 byte

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

Bentuk bersih:

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

Cobalah online!

Catatan

  • Bekerja dengan input hingga dan termasuk 170, input yang lebih tinggi menghasilkan loop yang tak terbatas, karena faktorialnya menghasilkan Infinityangka (secara teknis, ini adalah properti objek jendela yang tidak dapat ditulis, tidak dapat dihitung, dan tidak dapat dikonfigurasi).
  • Akurasi hilang untuk input 19 dan lebih tinggi, karena angka yang lebih tinggi dari 2 53 (= 9 007 199 254 740 992) tidak dapat disimpan secara akurat dalam JavaScript.

Penjelasan

Program ini terdiri dari dua loop. Yang pertama menghitung faktorial dari input, yang lain membagi hasilnya menjadi digit-nya dan menambahkannya menjadi satu. Kemudian jumlahnya dicetak, dan program selesai.

Mulai

Pertama, kita perlu menyiapkan tumpukan. Untuk bagian itu, kami menggunakan tiga instruksi pertama. IP dimulai pada baris keempat, menunjuk ke timur. Tumpukan kosong.

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

Kami akan menyimpan jumlah di bagian paling bawah tumpukan, jadi kita harus mulai dengan 0menjadi jumlah dengan menyimpannya di bagian bawah tumpukan. Maka kita perlu mendorong a1 , karena input awalnya akan dikalikan dengan angka sebelumnya. Jika ini nol, faktorial akan selalu menghasilkan nol juga. Terakhir kita membaca input sebagai integer.

Sekarang, tumpukannya [0, 1, input]dan IP berada di baris keempat, kolom keempat, menunjuk ke timur.

Lingkaran faktorial

Ini adalah loop sederhana yang mengalikan dua elemen teratas dari stack (hasil dari loop sebelumnya dan input - n, dan kemudian mengurangi input. Itu rusak ketika input mencapai 0. $Instruksi menyebabkan IP untuk melewatkan u- turn.Lop adalah bagian dari kubus berikut ini. IP dimulai pada baris keempat, kolom keempat.

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

Karena ^karakternya, IP mulai bergerak ke utara segera. Kemudian uberbalik IP dan bergerak satu ke kanan. Di bagian bawah, ada panah lain: <mengarahkan IP kembali ke ^. Tumpukan dimulai sebagai [previousresult, input-n], di mana njumlah iterasi. Karakter berikut dieksekusi dalam loop:

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

Kemudian bagian atas tumpukan (input berkurang) diperiksa 0oleh !instruksi, dan jika ya 0, theu karakter dilewati.

Jumlahkan angka

IP membungkus kubus, berakhir pada karakter terakhir pada baris keempat, awalnya menunjuk ke barat. Loop berikut terdiri dari hampir semua karakter yang tersisa:

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

Loop pertama-tama menghapus item teratas dari tumpukan (yang merupakan salah satu 10atau 0), dan kemudian memeriksa apa yang tersisa dari hasil faktorial. Jika itu telah dikurangi menjadi 0, bagian bawah tumpukan (jumlahnya) dicetak dan program berhenti. Jika tidak, instruksi berikut dijalankan (tumpukan dimulai sebagai [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]

Dan loop dimulai lagi, hingga factorial/10sama dengan 0.

Luke
sumber
3

C, 47 byte

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

pemakaian:

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));
}
pengguna84207
sumber
2

Python, 57 byte

import math
lambda n:sum(map(int,str(math.factorial(n))))

Cobalah online

mbomb007
sumber
Bisakah Anda menggunakan kembali ticks bukan str?
nedla2004
2
@ nedla2004 Itu akan menambahkan Lsekali faktorial cukup besar untuk menjadi panjang.
Kade
2

Batch, 112 byte

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

Nyaman set/abekerja pada nilai saat ini variabel, jadi itu bekerja secara normal di dalam satu loop. Hanya berfungsi hingga 12 karena keterbatasan tipe integer Batch, jadi secara teori saya bisa menghemat byte dengan mengasumsikan 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%

Tetapi dengan cara itu ada kegilaan ... Saya mungkin juga membuat hard-code daftar dalam hal itu (97 byte):

@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
Neil
sumber
2

JavaScript (ES6), 50 byte

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

Hanya berfungsi hingga n=22karena batasan akurasi floating-point.

Neil
sumber
2

Befunge 93 , 56 54 byte

Tersimpan 2 byte lakukan untuk menggunakan get bukannya kutipan. Ini biarkan saya menggeser 2 baris teratas lebih dari 1, mengurangi ruang putih yang tidak perlu.

Cobalah online!

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

Penjelasan:

&#:<                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.
MildlyMilquetoast
sumber
Anda benar. Saya sedang mengerjakan versi baru. FYI, saya menggunakan quickster.com, karena yang lain yang saya temukan tidak memperlakukan `` dengan benar ketika hanya ada satu # di stack.
MildlyMilquetoast
Terima kasih! Sepertinya kode ini hanya berfungsi dengan baik di versi Befunge-98 , mungkin karena metode put.
MildlyMilquetoast
48 byte yang juga menangani 0 dengan benar
Jo King
2

Javascript ES6 - 61 54 Bytes

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

EDIT: Terima kasih, Hedi dan ETHproduk karena telah memangkas 7 byte. Saya harus ingat trik t - = - j.

Marcus Dirr
sumber
1
Jawaban bagus! Anda dapat menyimpan beberapa byte dalam berbagai cara:n=>{a=_=>!_||_*a(~-_);t=0;for(j of''+a(n))t-=-j;return t}
ETHproduk
@ETHproductions Beberapa byte lagi dapat disimpan dengan eval:n=>eval(`for(j of''+(a=_=>!_||_*a(~-_))(n,t=0))t-=-j`)
Hedi
@Hedi aku tahu, aku mengambil satu langkah pada satu waktu :-)
ETHproduksi
2

AHK , 60 byte

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

AutoHotkey tidak memiliki fungsi faktorial bawaan dan fungsi loop memiliki nama panjang untuk variabel bawaannya. Loop pertama adalah faktorial dan yang kedua adalah menambahkan angka bersama.

Toast insinyur
sumber
2

J, 12 11 byte

Disimpan 1 byte berkat cole!

1#.10#.inv!

Ini hanya berlaku jumlah ( 1#.) untuk digit (menggunakan kebalikan invdari konversi basis #.dengan basis 10) dari faktorial ( !) argumen.

Uji kasus

Catatan: dua test case terakhir adalah bigints, seperti yang ditandai oleh trailing x.

   f=:10#.inv!
   (,. f"0) 10 19 469x 985x
 10    27
 19    45
469  4140
985 10053
Conor O'Brien
sumber
Anda dapat menggunakan "."0":untuk mendapatkan angka
Bolce Bussiere
11 byte: 1#.,.&.":@!yang membutuhkan presisi yang diperluas untuk kasus yang lebih kecil juga (tidak yakin mengapa). Juga 11 byte: 1#.10#.inv!.
cole
1

C, 63 60 byte

-3 byte untuk do...whileloop.

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

Tidak digabungkan dan digunakan:

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

main() {
 printf("%d\n",f(10));
}
Karl Napf
sumber
Apakah kita mendefinisikan f (n) sebagai intdefault?
Mukul Kumar
@MukulKumar ini adalah standar dalam C, jika tidak ada tipe maka intdiasumsikan.
Karl Napf