Tổng số chữ số


25

Thách thức là tính tổng chữ số của giai thừa của một số.


Thí dụ

Input: 10
Output: 27

10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800 và tổng các chữ số trong số 10! là 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27

Bạn có thể mong đợi đầu vào là một số nguyên trên 0. Đầu ra có thể là bất kỳ loại nào, nhưng câu trả lời phải nằm trong cơ sở tiêu chuẩn của ngôn ngữ mã hóa.


Các trường hợp thử nghiệm:

10    27
19    45
469   4140
985   10053

NB Một số ngôn ngữ không thể hỗ trợ số lượng lớn trên số nguyên 32 bit; đối với những ngôn ngữ đó, bạn sẽ không thể tính được các yếu tố lớn.

Liên kết OEIS ở đây nhờ Martin Ender


Đây là , vì vậy mã ngắn nhất trong các nhân vật sẽ thắng!


Số lượng đầu vào tối đa để mong đợi là gì? Với số nguyên 32 bit trong R, thử thách này không thể được giải quyết chính xác trong quá khứn>21
Billywob

1
@Billywob Đối với R thì bạn sẽ chỉ cần đến 20. Tôi sẽ chỉnh sửa câu hỏi để phản ánh điều này
george

Câu trả lời:





7

C ++ 11, 58 byte

Như lambda chưa đặt tên sửa đổi đầu vào của nó:

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

Một trong những trường hợp hiếm hoi khi C ++ mã của tôi là ngắn hơn so với mã C .

Nếu bạn muốn hỗ trợ các trường hợp lớn hơn, hãy chuyển sang C ++ 14 và sử dụng:

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

và cung cấp đối số gọi với ullhậu tố.

Sử dụng:

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

Ruby, 63 61 53 38 byte

Cách tiếp cận mới nhờ thao tác:

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

Cũ:

->n{(1..n).reduce(:*).to_s.chars.map(&:hex).reduce:+}
  • -3 byte nhờ Martin Ender
  • -5 byte nhờ GB

1
Cách nhàm chán cũ eval: ->n{eval"#{(1..n).reduce:*}".chars*?+}.
manatwork

6

Bình thường, 7 6 byte

Cảm ơn @Kade đã tiết kiệm cho tôi một byte

sj.!QT

Hãy thử trực tuyến!

Đây là lần đầu tiên tôi sử dụng Pyth, vì vậy tôi chắc chắn rằng câu trả lời của tôi có thể bị đánh golf khá nhiều.

Giải trình:

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

1
10được gán cho một biến T, vì vậy bạn có thể thực hiện điều này sj.!QT:)
Kade

Được rồi cảm ơn! Tôi sẽ thêm nó
BookOwl

Tốt đẹp! ssM`.!cũng làm công việc đó, cũng trong 6 byte.
hakr14

5

Haskell, 41 40 byte

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

Ví dụ sử dụng: f 985-> 10053.

Lập một danh sách từ 1đểx , tính toán sản phẩm của các thành phần danh sách, biến nó thành biểu diễn chuỗi của nó, biến mỗi ký tự thành một số và tính tổng chúng.

Chỉnh sửa: @Angs đã lưu một byte. Cảm ơn!


f x=sum$read.pure<$>(show$product[1..x])lưu một byte
Angs

5

Python, 54 byte

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

thay thế


Tôi chỉ đưa ra một phiên bản hơi tồi tệ này trông cách quá giống cho nó trở thành một câu trả lời riêng biệt. Bravo
osuka_

5

R, 58 53 byte

Chỉnh sửa: Đã lưu một byte nhờ @Jonathan Carroll và một cặp nhờ @Micky T

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

Thật không may, với số nguyên 32 bit, điều này chỉ hoạt động n < 22. Đưa đầu vào từ stdin và đầu ra thành thiết bị xuất chuẩn.

Nếu muốn độ chính xác cao hơn, người ta sẽ phải sử dụng một số thư viện bên ngoài như Rmpfr:

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

1
Tôi đã đạt được câu trả lời chính xác như bạn đã làm, sau đó tìm thấy mức tăng 1 byte trên c(x,"")vs paste(x): sum(as.integer(el(strsplit(c(factorial(scan()),""),"")))). Ép buộc kết quả giai thừa cho nhân vật và strsplittrả về nó như một danh sách thứ hai, do đó elvẫn hoạt động và trích xuất các phần tử danh sách đầu tiên.
Jonathan Carroll

2
làm thế nào về prod(1:scan())?
MickyT

1
cũng as.double nên đủ
MickyT

@MickyT Cảm ơn! Cập nhật.
Billywob

strtoilàm việc như một sự thay thế ngắn hơn as.double, tôi nghĩ.
Giuseppe

4

Pip , 8 byte

$+$*++,a

Hãy thử trực tuyến!

Giải trình

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

Xin lỗi, tôi thực sự đã quản lý để gửi câu trả lời 05AB1E trước bạn;).
Bạch tuộc ma thuật Urn

2
@carusocomputing: Hehe. Hãy cho tôi cơ hội để tìm hiểu một ngôn ngữ mới :)
Emigna

1
Tôi nghĩ bạn là người đầu tiên ngoài tôi sử dụng Pip cho câu trả lời golf không có mã đa âm. : D
DLosc



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;

@EyalLev Không có giới hạn được chỉ định trong câu hỏi. Làm thế nào bạn mong đợi để xử lý một giai thừa tương đương với lớn hơn 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}

Cảm ơn Martin đã giúp đỡ chơi golf.


3

Pushy , 4 byte

fsS#

Đưa ra đầu vào trên dòng lệnh : $ pushy facsum.pshy 5. Đây là sự cố:

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

3

Octave, 30 byte

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

Tính giai thừa bằng cách lấy sản phẩm của danh sách [1 2 ... n]. Chuyển đổi nó thành một chuỗi và trừ 48từ tất cả các phần tử (mã ASCII cho 0). Cuối cùng nó tổng hợp lại :)


3

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

Chắc chắn không phải là thanh lịch nhất nhưng cho thử thách

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

fold -1tiết kiệm một byte.
Chấn thương kỹ thuật số

@DigitalTrauma đã sửa! cảm ơn
Adam

3

C, 58 byte

Điều này là không hoàn hảo. Chỉ hoạt động những cái vì phải bắt đầu -1. Ý tưởng là sử dụng hai hàm đệ quy trong một hàm. Nó không dễ như tôi nghĩ.

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

Định dạng sử dụng và dễ hiểu:

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

Chỉnh sửa: Tôi tìm thấy metode cho phép sử dụng chức năng này nhiều lần nhưng sau đó độ dài là 62 byte.

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

Ý tưởng hay, nhưng tôi hoàn toàn không hiểu tại sao sẽ không ngắn hơn khi sử dụng một hàm để trả về giai thừa và một hàm khác để tính tổng chữ số, như a (b (10)). Là từ "trở lại" quá lâu để làm việc đó?
JollyJoker

Trả lại ăn nhiều. Tôi cố gắng tất nhiên. Có lẽ ai đó có thể làm điều đó ít nhất là tôi không thể có được công việc đó
teksturi

1
bạn có thể chấp nhận hai đối số để lưu một vài byte: codegolf.stackexchange.com/a/153132/77415
user84207

3

Perl 6 , 21 byte

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

Mở rộng:

{  # 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
}

Xin chúc mừng, bạn đã có câu trả lời không. 101010!
RudolfJelin

@ RudolfL.Jelínek Không có gì, trên StackOverflowMeta.StackExchange Tôi là số người dùng 1337
Brad Gilbert b2gills

3

Khối, 33 32 byte

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

Hình thức mạng:

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

Hãy thử trực tuyến!

Ghi chú

  • Hoạt động với đầu vào lên đến 170, đầu vào cao hơn dẫn đến một vòng lặp vô hạn, bởi vì giai thừa của chúng mang lại Infinity số (nói về mặt kỹ thuật, đây là thuộc tính không thể ghi, không thể đếm được và không thể cấu hình của đối tượng cửa sổ).
  • Độ chính xác bị mất cho đầu vào 19 trở lên, vì các số cao hơn 2 53 (= 9 007 199 254 740 992) không thể được lưu trữ chính xác trong JavaScript.

Giải trình

Chương trình này bao gồm hai vòng. Đầu tiên tính giai thừa của đầu vào, cái còn lại chia kết quả thành các chữ số của nó và cộng các số đó lại với nhau. Sau đó, tổng được in, và chương trình kết thúc.

Khởi đầu

Đầu tiên, chúng ta cần chuẩn bị ngăn xếp. Đối với phần đó, chúng tôi sử dụng ba hướng dẫn đầu tiên. IP bắt đầu trên dòng thứ tư, chỉ về phía đông. Ngăn xếp trống rỗng.

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

Chúng tôi sẽ giữ tổng số ở dưới cùng của ngăn xếp, vì vậy chúng tôi cần bắt đầu với 0 tổng bằng cách lưu trữ số đó ở dưới cùng của ngăn xếp. Sau đó, chúng ta cần phải đẩy một1 , vì đầu vào ban đầu sẽ được nhân với số trước nó. Nếu đây là 0, giai thừa sẽ luôn mang lại số không. Cuối cùng, chúng tôi đọc đầu vào như một số nguyên.

Bây giờ, ngăn xếp là [0, 1, input] và IP ở dòng thứ tư, cột thứ tư, chỉ về phía đông.

Vòng lặp nhân tố

Đây là một vòng lặp đơn giản nhân hai phần tử trên cùng của ngăn xếp (kết quả của vòng lặp trước và đầu vào - n, sau đó giảm đầu vào. Nó bị ngắt khi đầu vào đạt 0. Lệnh $khiến IP bỏ qua u- lần lượt. Vòng lặp là phần sau của khối. IP bắt đầu trên dòng thứ tư, cột thứ tư.

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

^đặc tính, IP bắt đầu di chuyển về phía bắc ngay lập tức. Sau đó, uxoay IP xung quanh và di chuyển nó sang bên phải. Ở phía dưới, có một mũi tên khác: <trỏ IP trở lại vào ^. Ngăn xếp bắt đầu như [previousresult, input-n], nơi nlà số lần lặp lại. Các ký tự sau được thực thi trong vòng lặp:

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

Sau đó, đỉnh của ngăn xếp (đầu vào giảm) được kiểm tra 0theo !hướng dẫn và nếu có 0,u ký tự sẽ bị bỏ qua.

Tổng các chữ số

IP bao quanh khối lập phương, kết thúc ở ký tự cuối cùng trên dòng thứ tư, ban đầu chỉ về phía tây. Vòng lặp sau bao gồm khá nhiều tất cả các ký tự còn lại:

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

Vòng lặp trước tiên xóa mục trên cùng khỏi ngăn xếp (là một trong hai 10hoặc 0), sau đó kiểm tra những gì còn lại của kết quả của giai thừa. Nếu điều đó đã được giảm xuống 0, phần dưới cùng của ngăn xếp (tổng) được in và chương trình dừng lại. Mặt khác, các hướng dẫn sau đây được thực thi (ngăn xếp bắt đầu như [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]

Và vòng lặp bắt đầu lại, cho đến khi factorial/10bằng 0.


3

C, 47 byte

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

sử dụng:

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

Python, 57 byte

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

Dùng thử trực tuyến


Bạn có thể sử dụng tick lại thay vì str?
nedla2004

2
@ nedla2004 Điều đó sẽ nối thêm một Lkhi giai thừa đủ lớn để trở thành dài.
Kade

2

Mẻ, 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%

Thuận tiện set/ahoạt động trên giá trị hiện tại của một biến, vì vậy nó hoạt động bình thường trong một vòng lặp. Chỉ hoạt động tối đa 12 do các giới hạn của loại số nguyên của Batch, vì vậy theo lý thuyết tôi có thể lưu một byte bằng cách giả sử 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%

Nhưng cách đó nằm ở sự điên rồ ... Tôi cũng có thể mã hóa danh sách trong trường hợp đó (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

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

Chỉ hoạt động tối đa n=22do giới hạn độ chính xác dấu phẩy động.


2

Befunge 93 , 56 54 byte

Đã lưu 2 byte để sử dụng get thay vì dấu ngoặc kép. Điều này cho phép tôi thay đổi 2 dòng trên cùng 1, giảm khoảng trắng không cần thiết.

Hãy thử trực tuyến!

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

Giải trình:

&#:<                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.

Bạn nói đúng. Tôi đang làm việc trên một phiên bản mới. FYI, tôi đang sử dụng quickster.com, bởi vì những người khác mà tôi thấy không đối xử chính xác với `` khi chỉ có một # trong ngăn xếp.
MildlyMilquetoast

Cảm ơn! Có vẻ như mã này chỉ hoạt động đúng trong phiên bản Befunge-98 , có lẽ là do phương thức put.
MildlyMilquetoast

48 byte cũng xử lý 0 chính xác
Jo King

2

Javascript ES6 - 61 54 byte

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

EDIT: Cảm ơn bạn Hedi và ETHproductions đã cạo 7 byte. Tôi sẽ phải nhớ rằng t - = - j trick.


1
Câu trả lời tốt đẹp! Bạn có thể lưu một vài byte theo nhiều cách khác nhau:n=>{a=_=>!_||_*a(~-_);t=0;for(j of''+a(n))t-=-j;return t}
Sản xuất ETH

@ETHproductions Một số byte khác có thể được lưu bằng eval:n=>eval(`for(j of''+(a=_=>!_||_*a(~-_))(n,t=0))t-=-j`)
Hedi

@Hedi Tôi biết, tôi đã thực hiện từng bước một :-)
ETHproductions

2

AHK , 60 byte

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

AutoHotkey không có chức năng giai thừa tích hợp và các hàm vòng lặp có tên dài cho các biến tích hợp của chúng. Vòng lặp đầu tiên là giai thừa và vòng thứ hai là cộng các chữ số lại với nhau.


2

J, 12 11 byte

Đã lưu 1 byte nhờ cole!

1#.10#.inv!

Điều này chỉ đơn giản áp dụng tổng ( 1#.) cho các chữ số (sử dụng nghịch đảoinv chuyển đổi cơ sở #.với cơ sở 10) của giai thừa ( !) của đối số.

Các trường hợp thử nghiệm

Lưu ý: hai trường hợp kiểm tra cuối cùng là các gợi ý, được đánh dấu bằng một dấu x.

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

Bạn có thể sử dụng "."0":để lấy chữ số
Bolce Bussiere

11 byte: 1#.,.&.":@!yêu cầu độ chính xác mở rộng cho các trường hợp nhỏ hơn (không chắc tại sao). Ngoài ra 11 byte : 1#.10#.inv!.
cole


1

C, 63 60 byte

-3 byte cho do...whilevòng lặp.

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

Ungolfed và cách sử dụng:

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

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

Chúng ta có định nghĩa f (n) inttheo mặc định không?
Mukul Kumar

@MukulKumar đây là tiêu chuẩn trong C, nếu không có loại thì intđược giả sử.
Karl Napf
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.