阶乘和


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链接在此感谢Martin Ender


这是,因此字符中最短的代码将获胜!


期望的最大输入数量是多少?对于R中的32位整数,此挑战无法准确解决n>21
Billywob

1
@Billywob对于R,那么您只需要转到20。我将编辑问题以反映这一点
乔治

Answers:





7

C ++ 11,58个字节

作为未命名的lambda,修改其输入:

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

我的C ++代码比C代码短的罕见情况之一。

如果要支持更大的情况,请切换到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

Ruby,63 61 53 38字节

通过操作的新方法:

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

旧:

->n{(1..n).reduce(:*).to_s.chars.map(&:hex).reduce:+}
  • -3个字节感谢Martin Ender
  • -5个字节,多亏了GB

1
旧的无聊eval方式:->n{eval"#{(1..n).reduce:*}".chars*?+}
manatwork '16

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

好,谢谢!我将其添加
BookOwl

真好!ssM`.!也会做这项工作,也以6个字节为单位。
hakr14

5

Haskell,41个 40字节

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

用法示例:f 985-> 10053

1到列出列表x,计算列表元素的乘积,将其转换为字符串表示形式,将每个字符转换为数字并将其求和。

编辑:@Angs保存了一个字节。谢谢!


f x=sum$read.pure<$>(show$product[1..x])保存一个字节
昂斯

5

Python,54个字节

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

代表


我只是想出了一个略差版本的这种看起来方式太相似了它是一个单独的答案。Bravo
osuka_

5

R,58 53字节

编辑:感谢@Jonathan Carroll保存了一个字节,感谢@Micky T保存了两个字节

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
我得到了与您完全相同的答案,然后发现c(x,"")vs paste(x):获得了1个字节的增益sum(as.integer(el(strsplit(c(factorial(scan()),""),""))))。将阶乘结果强制转换为character strsplit并将其作为第二个列表返回,因此el仍然可以工作并提取第一个列表元素。
乔纳森·卡洛尔

2
怎么样prod(1:scan())
MickyT

1
as.double 应该足够
MickyT '16

@MickyT谢谢!更新。
Billywob

strtoias.double我认为可以作为较短的替代品。
朱塞佩

4

,8字节

$+$*++,a

在线尝试!

说明

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

抱歉,我实际上已经在您之前发布了05AB1E答案;)。
魔术章鱼缸

2
@carusocomputing:呵呵。让我有机会研究一种新的语言:)
艾米娜(Emmina)

1
我认为您是除​​我之外第一个将Pip用作非多语言代码高尔夫答案的人。:D
DLosc


3

Brachylog,5个字节

$!@e+

在线尝试!

说明

基本上描述的算法:

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

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

Ruby,63 60 53 51字节

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

感谢Martin提供的高尔夫帮助。


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保存一个字节。
Digital Trauma

@DigitalTrauma已更正!谢谢
亚当

3

C,58字节

这不是完美的。仅适用于a,因为a开头必须为-1。这个想法是在一个函数中使用两个递归函数。这并不像我最初想象的那么容易。

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

编辑:我发现让多次使用此功能的方法,但长度为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
您可以接受两个参数来节省一些字节:codegolf.stackexchange.com/a/153132/77415
user84207 '18八月

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!
RudolfJelin

@RudolfL.Jelínek没什么,在StackOverflowMeta.StackExchange上,我的用户号码是1337
Brad Gilbert 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个输入(包括170个输入)时,较高的输入会导致无限循环,因为它们的阶乘会产生Infinity数字(从技术上讲,它是window对象的不可写,不可枚举和不可配置的属性)。
  • 输入19和更高版本的精度会丢失,因为不能将大于2 53(= 9 007 199 254 740 740 992)的数字准确存储在JavaScript中。

说明

该程序包含两个循环。第一个计算输入的阶乘,另一个将结果拆分为数字并将它们相加。然后打印总和,程序结束。

开始

首先,我们需要准备堆栈。对于这一部分,我们使用前三个说明。IP从第四行开始,指向东。堆栈为空。

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

我们将总和保留在堆栈的最底部,因此我们需要从0将总和存储在堆栈的底部开始。然后,我们需要推送一个1,因为输入将首先乘以之前的数字。如果为零,则阶乘也将始终产生零。最后,我们将输入读取为整数。

现在,堆栈位于[0, 1, input],IP位于第四行,第四列,指向东。

阶乘循环

这是一个简单的循环,它将堆栈的前两个元素(前一个循环的结果和输入-n相乘),然后递减输入。当输入达到0时中断。$指令使IP跳过u-循环是多维数据集的以下部分,IP从第四行第四列开始。

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

由于^字符的原因,IP立即开始向北移动。然后,u将IP转过来并将其向右移动一个。在底部,还有另一个箭头:<将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环绕立方体,最后到第四行的最后一个字符,最初指向西。以下循环几乎包含所有剩余字符:

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

循环首先从堆栈中删除最上面的项(100),然后检查阶乘结果的剩余内容。如果减小到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

Python,57个字节

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

在线尝试


您可以使用反勾而不是str吗?
nedla2004 '16

2
@ nedla2004 L一旦阶乘足够大就可以添加一个长整数。
卡德

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,因为我发现的其他对象在堆栈中只有一个#时没有正确对待。
MildlyMilquetoast '16

谢谢!看起来此代码仅在Befunge-98版本中正常工作,可能是由于put方法所致
MildlyMilquetoast,2016年

48个字节,也可以正确处理0
Jo King

2

使用Javascript ES6 - 61个 54字节

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

编辑:谢谢Hedi和ETHproductions削减了7个字节。我必须记住t-=-j的把戏。


1
好答案!您可以通过多种方式保存几个字节:n=>{a=_=>!_||_*a(~-_);t=0;for(j of''+a(n))t-=-j;return t}
ETHproductions 2016年

@ETHproductions可以使用eval保存更多字节:n=>eval(`for(j of''+(a=_=>!_||_*a(~-_))(n,t=0))t-=-j`)
Hedi

@Hedi我知道,我一次迈出了一步:-)
ETHproductions

2

AHK,60字节

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

AutoHotkey没有内置的阶乘函数,并且循环函数为其内置变量使用长名称。第一个循环是阶乘,第二个循环将数字加在一起。


2

J,12 11字节

感谢科尔节省了1个字节!

1#.10#.inv!

这简单地将sum(1#.)应用于数字(使用反inv参数的阶乘()基数转换的,#.底数为10!

测试用例

注意:最后两个测试用例是bigints,用尾随标记x

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

您可以"."0":用来获取数字
Bolce Bussiere

11个字节:1#.,.&.":@!在较小的情况下也需要扩展精度(不确定原因)。也是11个字节:1#.10#.inv!
科尔


1

C,63 60字节

-3个字节用于do...while循环。

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)定义为?
Mukul Kumar

@MukulKumar这是C语言中的标准,如果没有类型,则int假定为。
Karl Napf
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.