其他事实!


17

在数学中,由n!表示的非负整数n的阶乘,缩短的“事实” 是所有小于或等于n的正整数的乘积。例如5!1 * 2 * 3 * 4 * 5 = 120

根据惯例,空乘的0阶乘为1


这些是我们习惯的常规事实。让我们添加一些替代方法:

  1. 阶乘(上面定义)
  2. 双阶乘:n!= 1 + 2 + ... + n
  3. 三重因子:n!= 1-(2-(3-(...-n)))...)
  4. 四倍阶乘:n !!!! = 1 /(2 / /(3 ... / n)))...)。注意:这是浮点除法,而不是整数除法。

挑战

取一个非负整数输入n,紧跟着14个感叹号。输入看起来(完全)像这样:0!5!132!还是4个!!!。抱歉,在此挑战中,您可能不会采用灵活的输入格式。

输出量

输出应该是任何方便格式的结果。四阶阶乘的结果必须在小数点后至少2位,除了0 !!!! = 0

测试用例:

0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
---
0!! = 0
1!! = 1
2!! = 3
3!! = 6
4!! = 10
5!! = 15
6!! = 21
7!! = 28
8!! = 36
9!! = 45
10!! = 55
---
0!!! = 0
1!!! = 1
2!!! = -1
3!!! = 2
4!!! = -2
5!!! = 3
6!!! = -3
7!!! = 4
8!!! = -4
9!!! = 5
10!!! = -5
---
0!!!! = 0
1!!!! = 1
2!!!! = 0.5
3!!!! = 1.5
4!!!! = 0.375
5!!!! = 1.875
6!!!! = 0.3125
7!!!! = 2.1875
8!!!! = 0.27344
9!!!! = 2.4609
10!!!! = 0.24609

每种语言中最短的解决方案将获胜。


2
四重阶乘也可以是有理除法吗?
马丁·恩德

6
“双重析因”的定义很合适……
暴民埃里克(Erik the Outgolfer)

4
@Erik,这是另一种双重事实;-)
Stewie Griffin

1
@StewieGriffin顺便说一句0!-> 有点偷偷摸摸1
暴民埃里克(Erik the Outgolfer)'17年

5
标题应该是替代事实
数字创伤

Answers:


7

JavaScript(ES6),88个字节

s=>eval(([a,b]=s.split(/\b/),g=k=>+a?k-a?k+'_*+-/'[b.length]+`(${g(k+1)})`:k:+!b[1])(1))

测试用例

格式化和评论

s =>                                // given the input string s,
  eval(                             // evaluate as JS code:
    ( [a, b] = s.split(/\b/),       //   a = integer (as string) / b = '!' string
      g = k =>                      //   g = recursive function taking k as input
        +a ?                        //     if a is not zero:
          k - a ?                   //       if k is not equal to a:
            k + '_*+-/'[b.length] + //         append k and the operation symbol
            `(${g(k + 1)})`         //         append the result of a recursive call
          :                         //       else:
            k                       //         just append k and stop recursion
        :                           //     else:
          +!b[1]                    //       return 1 for multiplication / 0 otherwise
    )(1)                            //   initial call to g() with k = 1
  )                                 // end of eval()

7

外壳,15个字节

§!ëΠΣF-F/#'!oṫi

在线尝试!

说明

索引到功能列表:使用功能语言的乐趣。

§!ëΠΣF-F/#'!oṫi  Implicit input, say x = "6!!!"
              i  Convert to integer (parses the leading sequence of digits): 6
            oṫ   Descending range to 1: y = [6,5,4,3,2,1]
  ë              Four-element list containing the functions
   Π             product,
    Σ            sum,
     F-          left fold with subtraction (gives 0 for empty list), and
       F/        left fold with division (gives 0 for empty list).
 !               1-based index into this list with
         #'!     count of !-characters in input: gives F-
§                Apply to y and print implicitly: -3

我使用下降范围和左折,因为-/采取他们的论点在稻壳相反的顺序。


Indexing into a list of functions是哇...
埃里克Outgolfer

我想到了Haskell,然后我看到了……确实,这似乎是工作的正确工具。+1
alleks '17

这是果壳为:D
Leo

6

C#(.NET Core)134130128字节

s=>{double e=s.Split('!').Length,n=int.Parse(s.Trim('!')),i=n,r=n;for(;--i>0;)r=e>4?i/r:e>3?i-r:e>2?i+r:i*r;return n<1&e<3?1:r;}

在线尝试!

打高尔夫最好的部分是您在尝试解决挑战时学到的东西。在这一章中,我了解到在C#中,您可以修剪字符串中除空格以外的其他字符。

  • LiefdeWen节省了4个字节!
  • 2个字节保存,因为我并不需要1。减去至s.Split('!').Length,刚修好的限制e>4?i/r:e>3?i-r:e>2?i+r:i*rn<1&e<3?1:r

1
您可以使e n并且idouble避免为r声明它以节省4个字节。
LiefdeWen

1
@LiefdeWen或float保存另一个字节。
凯文·克鲁伊森


4

R113111字节

function(s){z=strtoi((n=strsplit(s,'!')[[1]])[1])
n=length(n)
`if`(z,Reduce(c('*','+','-','/')[n],1:z,,T),n<2)}

尝试一些测试用例!

松散:

function(s){
  n <- strsplit(s,"!")[[1]]          # split on "!"
  z <- strtoi(n[1])                  # turn to integer
  n <- length(n)                     # count number of "!"
  FUN <- c(`*`,`+`,`-`,`/`)[[n]]     # select a function
  right <- TRUE                      # Reduce (fold) from the right
  if( z > 0)                         # if z > 0
    Reduce(FUN, 1:z,,right)          # return the value
  else    
    (n < 2)                          # 1 if n = 1, 0 if n > 1
}

el(strsplit(s,"!")) 保存1个字节
bouncyball '17

4

Python3,124个 130 121 119字节

在这一点上,我认为递归是进一步节省字节的关键。

s=input()
l=s.count('!')
v=int(s[:-l])+1
print(eval((" *+-/"[l]+"(").join(map(str,range(1,v)))+")"*(v-2)or"0")+(l<2>v))

在“ 在线试用”上试用测试用例

-9个字节,感谢@ Mr.Xcoder

-2个字节,感谢@Felipe Nardi Batista


失败6!。它应该是720
Xcoder先生

我更新了Tio测试套件。
Xcoder先生


哦,是的,没发现

2
看得出

3

Pyth34 30字节

+uv++H@"/*+-"/Q\!G_tUK.vQKq"0!

在线尝试!

说明

+uv++H@"/*+-"/Q\!G_tUK.vQKq"0!"Q    Implicit: append "Q
                                    Implicit: read input to Q
                      .vQ           Evaluate Q as Pyth code. This evaluates the integer,
                                    any !'s are parsed as unary NOT for the next expression
                                    and discarded.
                     K              Save the result to K.
                    U               Get a list [0, 1, ..., K-1].
                   t                Drop the first item to get [1, 2, ..., K-1].
                  _                 Reverse to get [K-1, K-2, ..., 1].
 u                       K          Starting from G = K, for H in [K-1, K-2, ..., 1] do:
             /Q\!                     Count the !'s in Q.
      @"/*+-"                         Get the correct operator.
    +H                                Prepend the current H.
   +             G                    Append the previous value G.
  v                                   Evaluate as Python code.
                          q"0!"Q    See if Q == "0!".
+                                   If so, add 1.


2

05AB1E,27个字节

þL"/*+-"¹'!¢©è".»"ì.VD_нi®Θ

在线尝试!


你知道为什么„.»不起作用吗?
莱利

@Riley »是未完成的压缩字符串的一部分,因此它会出错,并且通常会在05AB1E中忽略该错误。
暴民埃里克(Erik the Outgolfer)'17年

"*+-/"èU在使用L跟进之后,我试图这样做,.»X但是它被视为X字符串,而不是命令,.»X.V甚至更糟糕。
魔术章鱼缸

@MagicOctopusUrn X没有评估。X.V是两个命令。
大公埃里克(Erik the Outgolfer)

@EriktheOutgolfer是的,但我希望在进行折页之前先评估一下。希望,没想到:(敢发誓有“使用单字符字符串作为二进命令链”什么的。
魔术章鱼金塔

2

Ruby83 80 79字节

->s{z=s.count ?!;s<?1?1+1<=>z:eval([*1..w=s.to_i]*(".0"+"_*+-/"[z]+?()+?)*~-w)}

在线尝试!

说明:

->s{
    # Get number of !
    z=s.count ?!

    # Special case: if the number is 0, then output 0 or 1 depending on z
    s<?1?1+1<=>z:

    # Otherwise build the full expression as a string and then evaluate it
    eval([*1..w=s.to_i]*(".0"+"_*+-/"[z]+?()+?)*~-w)
}

2

Java 8 141个 136 134字节

s->{float q=s.split("!",-1).length,n=new Float(s.split("!")[0]),i=n,r=n;for(;--i>0;r=q<3?i*r:q<4?i+r:q<5?i-r:i/r);return n<1&q<3?1:r;}

-5字节(141→136),感谢@CarlosAlejo的C#答案

说明:

在这里尝试。

s->{                                // Method with String parameter and float return-type
  float q=s.split("!",-1).length,   //  Amount of exclamation marks + 1
        n=new Float(s.split("!")[0]),
                                    //  The number before the exclamation marks
        i=n,                        //  Index (starting at `n`)
        r=n;                        //  Return sum (starting at `n`)
  for(;--i>0;                       //  Loop from `i-1` down to 1
    r=                              //   Change the result (`r`) to:
      q<3?                          //    If `q` is 2:
       i*r                          //     Multiply
      :q<4?                         //    Else if `q` is 3:
       i+r                          //     Addition
      :q<5?                         //    Else if `q` is 4:
       i-r                          //     Subtraction
      :                             //    Else (if `q` is 5):
       i/r                          //     Division
  );                                //  End of loop
  return n<1&q<3?                   //  Edge case if the input is `0!`:
          1                         //   Then return 1
         :                          //  Else:
          r;                        //   Return the result
}                                   // End of method

1
我在其他地方也看到过类似的答案...:-DI忘记了float比短的答案double
查理

@CarlosAlejo是的,我在最初的141字节回答后注意到了您的回答。更改float q=s.length()-(s=s.replace("!","")).length(),n=new Float(s)为当前答案后,我节省了5个字节。:)忘记添加“ 我现在注意到的字节节省了。”很抱歉。
凯文·克鲁伊森

哦,没关系,我很高兴您喜欢我的回答。:-)
查理

2

果冻 24 23 26  25 字节

+  3  2个字节的补丁会在误解后进行修复:(

×
+
_
÷
ṣ”!µḢVRṚȯL©Ị$®ŀ@/

完整程序(按程序位置引用的带帮助链接的单子链接)

在线尝试!或查看测试套件

怎么样?

× - Link 1, multiply: number, number

+ - Link 2, add: number, number

_ - Link 1, subtract: number, number

÷ - Link 1, divide: number, number

ṣ”!µḢVRṚȯL©Ị$®ŀ@/ - Main link: list of characters, a
ṣ”!               - split s at '!' characters
   µ              - monadic separation, call that b
    Ḣ             - head - pop and yield the digit list from b, modifying b
     V            - evaluate as Jelly code (get the number, say N)
      R           - range = [1,2,3,...,N]
       Ṛ          - reverse = [N,...,3,2,1]
            $     - last two links as a monad:
         L        -   length of modified b (number of '!' characters)
          ©       -   (copy to register)
           Ị      -   insignificant? (1 when just one '!', 0 when two or more)
        ȯ         - logical or (1 for "0!", 0 for "0!!...", the reversed-range otherwise)
                / - cumulative reduce by:
               @  -  with swapped arguments:
              ŀ   -    dyadic call of link at index:
             ®    -      recall value from register (number of '!' characters)


哦,哈哈-我在OP下读了您的评论有误-我以为他们的评分为0!定义为0,这将是错误的。
乔纳森·艾伦

现在所有问题都解决了:)
乔纳森·艾伦

太糟糕的TIO现在坏了,所以我无法测试它是否仍然无效。:(:P也太糟糕了,你不能使用/。对空列表d:编辑:显然有效0!0!!0!!!0!!!!+1。
在Outgolfer埃里克

2

自修改x86_64机器码,123字节

0f b6 0f 31 c0 eb 11 0f be c9 8d 04 80 8d 44 41 d0 0f b6 4f 01 48 ff c7 83 f9 21 75 ea b9 21 21 21 a1 33 0f 0f bc c9 81 c1 ff 07 00 00 c1 e9 03 0f b6 c9 89 ca 09 c2 74 35 55 48 89 e5 c7 45 fc 59 58 5c 5e 8a 4c 0d fc 88 0d 15 00 00 00 f3 0f 2a c8 83 f8 02 5d 7c 1f ff c8 0f 57 c0 f3 0f 2a c0 f3 0f 5e c1 83 f8 01 0f 28 c8 7f eb c3 f3 0f 10 05 03 01 00 00 c3 0f 28 c1 c3

为什么解释型语言能够动态地使用fancy eval而不是普通的机器代码运行代码?

尝试使用:

#include <stdio.h>
#include <sys/mman.h>
#include <errno.h>

char ff[] = "\x0f\xb6\x0f\x31\xc0\xeb\x11\x0f\xbe\xc9\x8d\x04\x80\x8d\x44\x41\xd0\x0f\xb6\x4f\x01\x48\xff\xc7\x83\xf9\x21\x75\xea\xb9\x21\x21\x21\xa1\x33\x0f\x0f\xbc\xc9\x81\xc1\xff\x07\x00\x00\xc1\xe9\x03\x0f\xb6\xc9\x89\xca\x09\xc2\x74\x35\x55\x48\x89\xe5\xc7\x45\xfc\x59\x58\x5c\x5e\x8a\x4c\x0d\xfc\x88\x0d\x15\x00\x00\x00\xf3\x0f\x2a\xc8\x83\xf8\x02\x5d\x7c\x1f\xff\xc8\x0f\x57\xc0\xf3\x0f\x2a\xc0\xf3\x0f\x5e\xc1\x83\xf8\x01\x0f\x28\xc8\x7f\xeb\xc3\xf3\x0f\x10\x05\x03\x01\x00\x00\xc3\x0f\x28\xc1\xc3";
int main()
{
    char* page = (char*)((unsigned long)((char*)ff) & (~0xfffLL));
    if (mprotect(page, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) {
        perror("mprotect");
        return -1;
    }
    float (*f)(char*) = (float (*)(char*))ff;
    char* testcases[] = { "0!","1!","2!","3!","4!","5!","6!","7!","8!","9!","10!",
                          "0!!","1!!","2!!","3!!","4!!","5!!","6!!","7!!","8!!","9!!","10!!",
                          "0!!!","1!!!","2!!!","3!!!","4!!!","5!!!","6!!!","7!!!","8!!!","9!!!","10!!!",
                          "0!!!!","1!!!!","2!!!!","3!!!!","4!!!!","5!!!!","6!!!!","7!!!!","8!!!!","9!!!!","10!!!!",
                        };
    for (int i = 0; i < 44; i++) {
        printf("%s -> %f\n", testcases[i], f(testcases[i]));
    }
}

部件:

_f:
100000d4f:  0f b6 0f    movzx   ecx, byte ptr [rdi]
100000d52:  31 c0   xor eax, eax
100000d54:  eb 11   jmp 17 <_f+18>
100000d56:  0f be c9    movsx   ecx, cl
100000d59:  8d 04 80    lea eax, [rax + 4*rax]
100000d5c:  8d 44 41 d0     lea eax, [rcx + 2*rax - 48]
100000d60:  0f b6 4f 01     movzx   ecx, byte ptr [rdi + 1]
100000d64:  48 ff c7    inc rdi
100000d67:  83 f9 21    cmp ecx, 33
100000d6a:  75 ea   jne -22 <_f+7>
100000d6c:  b9 21 21 21 a1  mov ecx, 2703302945
100000d71:  33 0f   xor ecx, dword ptr [rdi]
100000d73:  0f bc c9    bsf ecx, ecx
100000d76:  81 c1 ff 07 00 00   add ecx, 2047
100000d7c:  c1 e9 03    shr ecx, 3
100000d7f:  0f b6 c9    movzx   ecx, cl
100000d82:  89 ca   mov edx, ecx
100000d84:  09 c2   or  edx, eax
100000d86:  74 35   je  53 <_f+6E>
100000d88:  55  push    rbp
100000d89:  48 89 e5    mov rbp, rsp
100000d8c:  c7 45 fc 59 58 5c 5e    mov dword ptr [rbp - 4], 1583110233
100000d93:  8a 4c 0d fc     mov cl, byte ptr [rbp + rcx - 4]
100000d97:  88 0d 15 00 00 00   mov byte ptr [rip + 21], cl
100000d9d:  f3 0f 2a c8     cvtsi2ss    xmm1, eax
100000da1:  83 f8 02    cmp eax, 2
100000da4:  5d  pop rbp
100000da5:  7c 1f   jl  31 <_f+77>
100000da7:  ff c8   dec eax
100000da9:  0f 57 c0    xorps   xmm0, xmm0
100000dac:  f3 0f 2a c0     cvtsi2ss    xmm0, eax
100000db0:  f3 0f 5e c1     divss   xmm0, xmm1
100000db4:  83 f8 01    cmp eax, 1
100000db7:  0f 28 c8    movaps  xmm1, xmm0
100000dba:  7f eb   jg  -21 <_f+58>
100000dbc:  c3  ret
100000dbd:  f3 0f 10 05 03 01 00 00     movss   xmm0, dword ptr [rip + 259]
100000dc5:  c3  ret
100000dc6:  0f 28 c1    movaps  xmm0, xmm1
100000dc9:  c3  ret

稍后将添加说明。其基本思路是修改divss xmm0, xmm1指令的0x100000db0,并用其替换mulssaddsssubss或者divss根据提供的操作数。一个小技巧还用于解析输入字符串。

大会产生:

float f (char* s)
{
    int x;
    for (x=0; *s != '!'; s++) {
        x=10*x + (*s-'0');
    }
    unsigned char op = (__builtin_ctz(*(unsigned int *)s ^ 0xa1212121)-1) >> 3;
    if (x == 0 && op == 0) {
        return 1;
    }
    unsigned int lookup = 0x5e5c5859;
    unsigned char new_code = ((unsigned char*)&lookup)[op];
    asm("movb %0, 0x15(%%rip)" : : "r" (new_code));
    float sum;
    for (sum = x--; x>0; x--) {
        sum = x / sum;
    }
    return sum;
}

2

Haskell,105 102 98 96字节

0!3=0
x!y=foldr([(*),(+),(-),(/)]!!y)([1,0,0,1]!!y)[1..x]
f s|[(n,b)]<-lex s=read n!(length b-1)

感谢Zgarb和nimi,节省了9个字节。

在线尝试。


@Zgarb你是对的。固定。
Cristian Lupascu

我认为您也可以放下括号read nf=按照我们的规则,这是不必要的。
Zgarb

@Zgarb再次正确:)。谢谢!
Cristian Lupascu

切换回命名函数并使用lex将节省两个字节:f s|[(n,b)]<-lex s=read n!(length b-1)
nimi

@nimi哇,谢谢!我对Haskell非常新,甚至我都不知道lex。棒极了!:)我看不到如何保存字节-在此之后我得到了99个字节。
Cristian Lupascu

1

盖亚26 25字节

ẋ)@d┅v;l“×+⁻÷”=“ₔ⊢”+e¤ḥ!∨

在线尝试!

说明

ẋ                          Split the input into runs of the same character.
 )                         Get the last one (the !'s).
  @                        Push an input (since there's none left, use the last one).
   d                       Parse as number (ignores the !'s).
    ┅v                     Get the reverse range: [n .. 1]
      ;                    Copy the ! string
       l“×+⁻÷”=            Get its length and index into this string of operators.
               “ₔ⊢”+       Append 'ₔ⊢' to the operator.
                    e      Eval the resulting string, which is "reduce by <operator> with
                            swapped arguments." Reducing an empty list gives 0.
                     ¤     Bring the !'s back to the top.
                      ḥ!   Remove the first character and check if it's empty.
                        ∨  Logical OR; turns 0 from 0! to 1, doesn't change anything else.


1

APL(Dyalog),30字节

受到lstefano解决方案的启发。

{0::0⋄(⍎'×+-⌹'⊃⍨≢⍵~⎕D)/⍳⍎⍵∩⎕D}

在线尝试!

{} 匿名函数,其中参数由表示

0:: 如果发生任何错误:

  0 返回零

 现在尝试:

  ⍵∩⎕D 参数的交点和该组的d igits(去除感叹号)

   执行(将其转换为数字)

  ɩ那ndices

  ()/ 在词之间插入以下功能(根据需要APL是正确的关联):

   ⍵~⎕D 没有数字的论点(留下感叹号)

   计算(即多少个感叹号)

  '×+-⌹'⊃⍨ 使用它从符号列表中选择*

   执行(将符号转换为函数)


使用(矩阵除法)代替÷(常规除法)在空列表上导致错误


是什么 ::在dfn做?
扎卡里

这是一个错误防护。如果在设置了错误保护之后的任何时间,则错误出现在左侧的任何数字(0 = 1…999、1000 = 1001…)::发生事件,则该数字,然后::立即返回右侧的值。
亚当

好吧,我从来不知道,谢谢!
扎卡里


0

Dyalog APL,至少29个字符

{(⍎i⊃'×+-÷')/⍳⍎⍵↓⍨-i←+/'!'=⍵}

该表达式是正确的。通过所有测试用例0!!!!它给出的,1而不是要求的0,这是因为在APL中,空向量的减少应该返回用于减少功能的中性元素。对于1的商,目前我没有时间尝试对其进行修复,但是我将其留在这里以备不时之需。


下雨了:{0::0⋄(⍎'×+-⌹'⊃⍨≢⍵~⎕D)/⍳⍎⍵∩⎕D} 在线试用!
亚当

很酷!如果您声称它是您的解决方案,那么我根本不介意,因为差异远大于相似之处。
lstefano



0

Mathematica,152个字节

(T=ToExpression;If[#=="0!!!!",0,s=T@StringCount[#,"!"];t=T@StringDrop[#,-s];{#!,i~Sum~{i,#},Sum[-i(-1)^i,{i,#}],N@Product[1/i^(-1)^i,{i,#}]}[[s]]&[t]])&

0

Javascript,111 163字节

s=>([a,b]=s.split(/\b/),c=b.length,a==0&c==1||eval((p=[...Array(+a+1).keys()].slice(1).join(c-1?c-2?c-3?'/(':'-(':'+':'*'))+')'.repeat((p.match(/\(/g)||[]).length)))

可读版本

s=>([a,b]=s.split(/\b/),c=b.length,a==0&c==1||eval((p=
[...Array(+a+1).keys()].slice(1).join(c-1?c-2?c-3?'/(':'-
(':'+':'*'))+')'.repeat((p.match(/\(/g)||[]).length)))
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.