重复!阶乘!


34

不要与查找阶乘相混淆

介绍

整数的阶乘n可以由n计算 = Ñ × ñ - 1 × ñ - 2 × × 2 × 1

ñ=ñ×ñ-1个×ñ-2××2×1个

这是相对容易的,没有什么新鲜的。但是,阶乘可以扩展为双阶乘,例如

ñ=ñ×ñ-2×ñ-4××4×2
为偶数,并且
ñ=ñ×ñ-2×ñ-4××3×1个
为奇数。但是我们不仅限于双重析因。例如
n!!!=n×(n3)×(n6)×(...)×6×3
n!!!=n×(n3)×(n6)×(...)×5×2
ñ=ñ×ñ-3×ñ-6××4×1个
取决于起始值。

总结:

ñķ={1个如果 ñ=0ñ如果 0<ñķññ-ķķ如果 ñ>ķ
其中
ñķ=ñķ
或者用简单的英语:反复从基数中减去阶乘计数,然后将所有所得的正整数相乘。

挑战

编写一个函数,该函数将为任何非负整数计算任何种类的重复阶乘。

输入项

要么

  • 字符串,包含非负十进制整数,后跟1个或多个感叹号。EG "6!""9!!""40!!!!!!!!!!!!!!!!!!!!"

要么

  • 相同的值由两个整数表示:一个非负基值和一个代表阶乘计数的正值。可以根据默认I / O规则中的任何格式完成此操作。

输出量

所述计算的结果。

挑战备注

  • 0!等于1定义。您的代码必须说明这一点。
  • 阶乘计数受
    0<F一种CŤØ[R一世一种 CØüñŤb一种sË v一种üË
    在该范围之外,则可以自由地输出任何。除了0!,这是该规则的唯一例外。

例子

Input                              Output

3!!!                               3
0!                                 1
6!                                 720
9!!                                945
10!!!!!!!!                         20
40!!!!!!!!!!!!!!!!!!!!             800
420!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  41697106428257280000000000000000

尝试使用非Golf的Python实现:在线尝试!

一般说明


6
示例列出0!了示例,但挑战性说明说阶乘计数将小于或等于基值。
乔纳森·艾伦

1
不会3 !!!为零?N *(N-3)= 3 *(3-3)= 0。
ouflak

2
@ouflak如果它像1!那样工作,不是真的。更像是1!= 1. 2!= 2. 3 !!!=3。没有计算,因为您处在递归的结尾。产品中没有0,否则每个阶乘最终都会降为0。
V. Courtois

4
3!!!!!!!不应未定义-它应该只给出答案3。与1!!=1(未定义)相同。同样,您的输入规范指出,将始终至少有一个!,因此第一个示例3不符合规范。
格雷格·马丁

3
@FabianRöling:但这不是事实。它(3!)!不是从阶乘中删除术语。这是一个令人误解的名字;我进来是假设它将要在链中重复应用阶乘函数,并且必须仔细阅读以了解其实际含义。幸运的是,这个问题确实能够清楚地解释它。 一个更好的名字可能是步阶阶乘或阶阶阶乘等等。
彼得·科德斯

Answers:



13

ArnoldC702个698 634字节

LISTEN TO ME VERY CAREFULLY f
I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE n
I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE p
GIVE THESE PEOPLE AIR
HEY CHRISTMAS TREE r
YOU SET US UP 1
HEY CHRISTMAS TREE c
YOU SET US UP 0
STICK AROUND n
GET TO THE CHOPPER r
HERE IS MY INVITATION r
YOU'RE FIRED n
ENOUGH TALK
GET TO THE CHOPPER n
HERE IS MY INVITATION n
GET DOWN p
ENOUGH TALK
GET TO THE CHOPPER c
HERE IS MY INVITATION 0
LET OFF SOME STEAM BENNET n
ENOUGH TALK
BECAUSE I'M GOING TO SAY PLEASE c
GET TO THE CHOPPER n
HERE IS MY INVITATION 0
ENOUGH TALK
YOU HAVE NO RESPECT FOR LOGIC
CHILL
I'LL BE BACK r
HASTA LA VISTA, BABY

在线尝试!

转换为伪代码:

f(n,p) {
  r=1;
  c=0;
  while (n) {
    r=r*n;
    n=n-p;
    c=n<0;
    if (c) n=0;
  }
  return r;
}

注意:ArnoldC只有一种数据类型:16位带符号整数。因此,我无法测试420!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!此案。


只是对您的伪代码感到好奇。变量“ c”的作用是什么?
ouflak

@ouflak我编辑了几次答案却忘记了。该c变量实际上存储n和之间的比较值0
查理

+1,然后借用它(减去“ c”)作为我的LUA答案。
ouflak

12

果冻,4 字节

RṚmP

在线尝试!

怎么样?给定ñķñ1个RṚmķññ-ķñ-2ķñ-ñ/ķķP


效果很好,最后很简单。我一点也不了解果冻,但至少看起来不错:)
V. Courtois

1
ñķñ1个RṚmķññ-ķñ-2ķñ-ñ/ķķP
Xcoder先生

哈哈,非常感谢。有一天,我可能要在这个语言高尔夫球,所以我必须学习这些单子,二元体系等
五库尔图瓦

看起来像CJam的替代方法:r1mP
大决战者埃里克(Erik)

1
@KyeWShi Jelly有自己的代码页,因此它包含的256个字符中的每一个都编码为1个字节。
Xcoder先生

8

APL(Dyalog扩展),7 字节SBCS

匿名默认前缀功能。需要[n,b]作为参数。

×/-\…1¨

在线尝试!

 每个参数一个 [1,1]

-\ 累积差异; [n,n-b]

 使用左参数的第二个元素作为步长指示符的范围,例如 [9,7]继续5

×/ 产品


7

Haskell,21个字节

n%a=product[n,n-a..1]

在线尝试!

将内置乘积函数与步进范围枚举相结合,可以克服我可以递归编码的问题(即使节省了一个字节)。

22字节

n%a|n<1=1|m<-n-a=n*m%a

在线尝试!

这是一个以字符串格式输入的解决方案,例如 9!!,我认为这更有趣。

42字节

(\[(n,a)]->product[n,n-length a..1]).reads

在线尝试!


2
我认为您可以将递归解决方案缩短至n%a|n<1=1|m<-n-a=n*m%a
较差的


5

JavaScript(ES6),21个字节

将输入作为(k)(n)

k=>g=n=>n<1||n*g(n-k)

在线尝试!

要么 24个字节以支持BigInts。


JavaScript(ES6),55个字节

使用质询中描述的格式将输入作为字符串。

s=>(a=s.split`!`,k=a.length-1,g=n=>n<1||n*g(n-k))(a[0])

在线尝试!


5

空格,91字节

[S S S T    N
Push_1][S N
S _Duplicate_1][S N
S _Duplicate_1][T   N
T   T   _Read_STDIN_as_integer_(base)][T    T   T   _Retrieve_base][S S S N
_Push_0][T  N
T   T   _Read_STDIN_as_integer_(factorial)][N
S S N
_Create_Label_LOOP][S N
S _Duplicate_base][S S S T  N
_Push_1][T  S S T   _Subtract][N
T   T   S N
_If_negative_jump_to_Label_PRINT_RESULT][S N
S _Duplicate_base][S T  S S T   S N
_Copy_0-based_2nd_(result)][T   S S N
_Multiply][S N
T   _Swap_top_two][S S S N
_Push_0][T  T   T   _Retrieve_factorial][T  S S T   _Subtract][N
S N
N
_Jump_to_Label_LOOP][N
S S S N
_Create_Label_PRINT_RESULT][S N
N
_Discard_top][T N
S T _Print_result_as_integer]

字母S(空格),T(制表符)和N(换行符)仅作为突出显示而添加。
[..._some_action]仅作为说明添加。

在线尝试(仅使用空格,制表符和换行符)。

伪代码中的解释:

Integer result = 1
Integer base = STDIN as integer
Integer factorial = STDIN as integer
Start LOOP:
  If(base <= 0):
    Call function PRINT_RESULT
  result = result * base
  base = base - factorial
  Go to next iteration of LOOP

function PRINT_RESULT:
  Print result as integer to STDOUT


4

Perl 6,22个字节

{[*] $^a,*-$^b...^1>*}

在线尝试!

匿名代码块,它返回从第一个输入开始,范围的乘积,从第二个递减到直到它低于1,最后一个数字除外。这适用于0,因为reduce by product的基本情况为1,所以输出为1。


4

05AB1E10 8 7 字节

ݦRIιнP

输入为两个单独的输入:第一个输入为base;第二个输入是factorial

在线尝试验证所有测试用例

-2个字节,感谢@ Mr.Xcoder
-1个字节感谢@JonathanAllan

说明:

Ý        # Create a list in the range [0, (implicit) base-input]
 ¦       # And remove the first item to make it the range [1, base]
         # (NOTE: this is for the edge case 0. For the other test cases simply `L` instead
         #  of `ݦ` is enough.)
  R      # Reverse this list so the range is [base, 1]
   Iι    # Uninterleave with the second input as step-size
         #  i.e. base=3, factorial=7: [[3],[2],[1],[],[],[],[]]
         #  i.e. base=10, factorial=8: [[10,2],[9,1],[8],[7],[6],[5],[4],[3]]
         #  i.e. base=420, factorial=30: [[420,390,360,...,90,60,30],[419,389,359,...],...]
     н   # Only leave the first inner list
      P  # And take the product of its values
         # (which is output implicitly as result)

原始的10 个字节的答案:

L0KD¤-IÖÏP

输入为两个单独的输入:第一个输入为base;第二个输入是factorial

在线尝试验证所有测试用例

说明:

L           # Create a list in the range [1, (implicit) base-input]
 0K         # Remove all 0s (edge case for input 0, which will become the list [1,0])
   D        # Duplicate this list
    ¤       # Get the last value (without popping)
            # (could also be `Z` or `¹` for max_without_popping / first input respectively)
     -      # Subtract it from each item in the list
      IÖ    # Check for each if they're divisible by the second factorial-input
        Ï   # In the list we copied, only leave the values at the truthy indices
         P  # And take the product of those
            # (which is output implicitly as result)

1
这6 byter: (LR²ιнP试试它的在线)适用于所有的测试用例,除了0
Xcoder先生

但我想0大小写最多可以固定为2个字节。如果您想出一种方法来解决它,则可以采取:) 编辑:也许LR²ιн0KP是8个字节?
Xcoder先生

@ Mr.Xcoder不错的答案!绝对不要对给定步骤使用非交错。:)
凯文·克鲁伊森

0K应该是不必要的,因为0!规范中的输入无效(即使示例中已包含该输入)-我对此进行了评论
乔纳森·艾伦

1
... 如果 0!在输入域中,则ݦRXιнP保存一个字节。
乔纳森·艾伦

4

x86-64机器码,12个字节

在32位模式下,相同的机器代码执行相同的操作;在16位模式下,对于16位整数执行相同的操作。

这是一个函数,调用与ARGS n=RCXk=ESI。输入中的32位值EAX

可使用带有伪参数的x86-64 System V调用约定从C进行调用,以将实际args放入正确的寄存器中。uint32_t factk(int, uint32_t k, int, uint64_t n); 我不能只使用Windows x64,因为1-操作数mul掩盖了RDX,并且我们不希望REX前缀访问R8 / R9。 n不能在高32位中包含任何垃圾,因此JRCXZ可以工作,但除此之外,它们都是32位。

NASM列表(相对地址,机器代码,源)

 1                         factk:
 2 00000000 6A01             push 1
 3 00000002 58               pop rax             ; retval = 1
 4 00000003 E306             jrcxz  .n_zero      ; if (n==0) return
 5                         .loop:                ; do {
 6 00000005 F7E1              mul   ecx            ; retval *= n  (clobbering RDX)
 7 00000007 29F1              sub   ecx, esi       ; n -= k
 8 00000009 77FA              ja   .loop         ; }while(sub didn't wrap or give zero)
 9                         .n_zero:
10 0000000B C3               ret

0xc = 12个字节


或10个字节(如果我们不需要处理 n=0特殊情况,,而忽略jrcxz

对于标准阶乘,您将使用 loop代替sub / ja来节省2个字节,但是使用完全相同的代码。


测试调用者传递argck,用n硬编码。

align 16
global _start
_start:
  mov  esi, [rsp]
;main:
  mov  ecx, 9
  call factk

  mov  esi, eax
  mov  edx, eax
  lea  rdi, [rel print_format]
  xor  eax, eax
extern printf
  call printf
extern exit
  call exit

section .rodata
print_format: db `%#x\t%u\n`

```




3

Java 10,44个字节

f->b->{int r=1;for(;b>0;b-=f)r*=b;return r;}

以阶乘为第一输入,以base为第二。

在线尝试。

由于有限的整数范围(32位),以上内容不适用于最大的测试用例。为了解决这个问题,我们可以使用BigIntegers,它恰好大小的两倍-88 79字节

f->b->{var r=f.ONE;for(;b.signum()>0;b=b.subtract(f))r=r.multiply(b);return r;}

-9个字节,感谢@OlivierGrégoire

在线尝试。

说明:

f->b->{       // Method with two integer parameters and integer return-type
  int r=1;    //  Result-integer, starting at 1
  for(;b>0;   //  Loop as long as the base is still larger than 0
      b-=f)   //    After every iteration: decrease the base by the factorial
    r*=b;     //   Multiply the result by the base
  return r;}  //  Return the result


@OlivierGrégoireNp,谢谢!:)
Kevin Cruijssen



2

MathGolf7 6个字节

╙╒x%ε*

在线尝试!

找到了处理0的聪明方法!无需更改其他测试用例。输入为k n(反向顺序),这有助于隐式弹出。

说明

╙        maximum of two elements (pops largest of k and n,
         which is n for every valid case except 0!, where 1 is pushed)
 ╒       range(1,n+1)
  x      reverse int/array/string
   %     slice every k:th element
    ε*   reduce list with multiplication

2

附件21 19字节

${x<y∨x*$[x-y,y]}

在线尝试!非常直接的递归实现。(注意:true本质上是1,因为它可以在算术运算中用作1。)这是我为此站点编写的少数程序之一,使用unicode运算符可以节省字节(准确地说是1)。

备择方案

20个字节: ${x<y or x*$[x-y,y]}

21个字节: Prod@${{_%y=x%y}\1:x}

27个字节: ${x*[`1,$][x>y][x-y,y]∨1}

27个字节: ${If[x>y,x*$[x-y,y],_or 1]}

27个字节: ${x*[`1,$][x>y][x-y,y]or 1}

29个字节: ${If[x>y,x*$[x-y,y],_+not _]}


2

92 73 61字节

fn f(n:i128,k:i128)->i128{if n<=0{return 1}return n*f(n-k,k)}

我才刚刚开始学习生锈,所以我敢肯定这可以缩短。将随着我的学习而更新。返回值应为i128为了计算最后的测试。

编辑:递归更短。

在线尝试!

您可以添加自己的测试,或编辑现有测试之一。


2

q59 57 55 53字节

{prd 2+(&)1_i=last i:("J"$x(&)not[n])#(!)sum n:"!"=x}

说明:

q)x:"12!!" / let our input be 12!!, assign to x
q)sum n:"!"=x / count "!"s
2i
q)(!)sum n:"!"=x / (!)m -> [0,m)
0 1
q)("J"$x(&)not[n]) / isolate the number in input
12
q)("J"$x(&)not[n])#(!)sum n:"!"=x / x#y means take x items from list y, if x>y, circle around
0 1 0 1 0 1 0 1 0 1 0 1
q)i:("J"$x(&)not[n])#(!)sum n:"!"=x / assign to i
q)i
0 1 0 1 0 1 0 1 0 1 0 1
q)(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / take last elem of i and see which are equal in i
010101010101b
q)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / drop first elem
10101010101b
q)(&)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / indices of 1b (boolean TRUE)
0 2 4 6 8 10
q)2+(&)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / add 2 across array
2 4 6 8 10 12
q)prd 2+(&)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / product across array
46080

这也是k的版本(相同的逻辑),42 41字节

{*/2+&1_i=last i:("J"$x@&~:n)#!+/n:"!"=x}

欢迎光临本站!我已经在您的帖子中添加了代码格式,可以在行前使用四个空格,也可以使用三引号将其括起来。
小麦巫师

@ SriotchilismO'Zaic感谢:-)
乱写

1
我建议添加一个解释,也许还可以链接到TIO之类的在线解释器。仅代码答案通常会自动标记为低质量。
mbomb007

@ mbomb007有趣。有机器人标记答案吗?低质量的提交会怎样?我会尽快更新!
乱写

是的,有一个机器人。StackExchange使用漫游器来寻找潜在的垃圾邮件和低质量的答案。具有足够高声誉的人可以查看审阅队列。meta.stackexchange.com/a/161391/285610
mbomb007

1

物理,22字节

f=>n;k:n<1||n*f[n-k;k]

在线尝试!


26字节

重新学习如何使用我自己的“语言” \ o / ...如果两年前我知道如何编写解析器,那将是20字节:(

->n;k:GenMul##[n…1]{%%k}

要么

->n;k:GenMul##Range[n;1;k]

在线尝试!


1

视网膜,66字节

^0
1
\d+
*!,
+`(!+)(!+),\1$
$1$2,$2,$1
!+$
1
+`(!+),(\d+)
$.($2*$1

在线尝试!链接包括更快的测试用例。没有惊叹号的摩尔数。说明:

^0
1

修复0!

\d+
*!,

转换n为一元并添加分隔符。

+`(!+)(!+),\1$
$1$2,$2,$1

反复减去knn>k,并收集结果。

!+$
1

替换k1(十进制)。

+`(!+),(\d+)
$.($2*$1

依次乘以每个中间值,转换为十进制。




1

Forth(gforth),50个字节

: f 1 1 2over / 1+ 0 do 2over i * - 1 max * loop ;

在线尝试!

代码说明

: f                \ start a new word definition
  1 1              \ add placeholder and accumulator to stack
  2over / 1+       \ get the number of times to run the loop (num/factorial + 1)
  0 do             \ start loop from 0 to num/factorial
    2over          \ copy num and factorial to the top of the stack
    i * -          \ get the current number to multiply by (num - factorial * i)
    1 max          \ make sure it can't be 0 or negative [set to 1 if it is]
    *              \ multiply accumulator by result
  loop             \ end loop
;                  \ end the word definition           



1

盖亚(Gaia),6个字节

…)¦v%Π

在线尝试!

需要输入为nk,所以输入3 43!!!!

…	 push [0...n-1], or [] if n == 0
 )¦	 increment each value (does nothing if [])
   v	 reverse list
    %	 take every k'th element
     Π	 product; product([]) = 1.
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.