追加の事実!


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. 4つの階乗:n !!!! = 1 /(2 /(3 ... / n)))...)。注:これは整数除算ではなく、浮動小数点除算です。

チャレンジ

非負の整数入力を取るN、直接間続く1及び4感嘆符。入力は(まったく)次のようになります:0!5 !! 132 !!! または4 !!!! 。このチャレンジでは、柔軟な入力形式を想定していない可能性があります。申し訳ありません。

出力

出力は、任意の便利な形式での結果でなければなりません。4倍階乗の結果は、0 !!!!を除き、小数点の後に少なくとも2桁ある必要があります= 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
「二重階乗」の定義は適切です...
エリックアウトゴルファー

4
@エリック、それは別の二重の事実です;
スティーヴィー・グリフィン

1
@StewieGriffinところで、ちょっと卑劣なのは0!-> 1
エリックアウトゴルファー

5
タイトルは別の事実で
デジタル外傷

回答:


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

Huskでは逆の順序で引数-/取るため、降順の範囲と左折りを使用します。


Indexing into a list of functionsis woah ...
エリックアウトゴルファー

私はHaskellのことを考えていたのですが、それを見ると...本当に仕事に適したツールのようです。+1
alleks

これは、ハスクが何のために作られたかです:D-
レオ

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バイト節約!
  • 私はする1を減算する必要がないので、2つのバイトが保存されs.Split('!').Length、ただで限界を修正e>4?i/r:e>3?i-r:e>2?i+r:i*rしてn<1&e<3?1:r

1
あなたは作ることができますe nし、iまた、double4つのバイトを保存するには、rのためにそれを宣言避けるために。
-LiefdeWen

1
@LiefdeWenまたはfloat別のバイトを保存します。
ケビンCruijssen


4

R113 111バイト

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バイト節約
弾むボール

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

オンラインで試すのテストケースをお試しください!

@ Mr.Xcoderのおかげで-9バイト!

@Felipe Nardi Batistaに感謝-2バイト!


6で失敗します!。720である必要があります。
Xcoder氏17

Tioテストスイートを更新しました。
Mr Xcoder


そうそう、確かに、それを発見しませんでした
氏Xcoder


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.

を使用.Uするとバイトが節約されます。
エリックアウトゴルファー

2

05AB1E、27バイト

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

オンラインでお試しください!


なぜ„.»機能しないのか知っていますか?
ライリー

@Riley »は未完成の圧縮文字列の一部であるため、エラーになり、通常05AB1Eのように、エラーは無視されます。
エリックアウトゴルファー

私はフォローアップを"*+-/"èU使用した後、それをしようとしLました.»XX、コマンドで.»X.Vはなく文字列として扱い、さらに気味が悪いです。
魔法のタコUr

しょーた Xは評価されません。X.V2つのコマンドです。
エリックアウトゴルファー

@EriktheOutgolferええ、しかし、私はそれがフォールドを処理する前に評価されることを望んでいました。期待して。、:(期待していないことがあった誓っていたかもしれないか、何か「進チェーンのコマンドとして単一の文字列を使用する」。
マジックタコ壺

2

ルビー83 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バイト節約できました。:) 私が今気づいた「おかげで保存されたバイト数」を追加するのを忘れました。
ケビンCruijssen

ああ、決して気にしないで、あなたが私の答えを気に入ってくれてうれしいです。:
チャーリー

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)

失敗し0!ます。
エリックアウトゴルファー

ああ、ははは-私はOPの間違ったあなたのコメントを読んでいた-私は彼らが0を作ったと思った!間違っている0として定義されます。
ジョナサンアラン

すべて修正済み:)
ジョナサンアラン

あまりにも悪いTIOが今壊れているので、まだ無効かどうかをテストできません。:(:また、Pは、使用できないことがあまりにも悪い/。空のリストにD:EDIT:について明らかに有効な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

なぜインタープリタ言語は空想でコードを動的に実行できるのか eval sで、普通のマシンコードではないのですか

で試してください:

#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その通りです。修繕。
クリスチャンルパスク

かっこを捨てることもできると思いますがread n私たちの規則に従ってf=不要です。
ズガルブ

@Zgarb再び:)。ありがとう!
クリスチャンルパスク

名前付き関数に切り替えて使用すると、lex2バイト節約されますf s|[(n,b)]<-lex s=read n!(length b-1)
-nimi

@nimiわあ、ありがとう!私はHaskellが初めてなので知りませんでしたlex。すごい!:)しかし、それがどのようにバイトを節約するかわかりません-この後99バイトを取得します。
クリスチャンルパスク

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(ダイアログ)、30バイト

lstefanoのソリューションに触発されました

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

オンラインでお試しください!

{} 引数が次の式で表される匿名関数

0:: エラーが発生した場合:

  0 ゼロを返す

 今試してください:

  ⍵∩⎕D 引数とD igits のセットの交差点(感嘆符を削除)

   それを実行する(数値に変換する)

  ɩそれの ndices

  ()/ (必要に応じて、APLは右結合です)用語間に次の関数を挿入します。

   ⍵~⎕DD igitsの ない引数(感嘆符を残す)

   集計(つまり、感嘆符の数)

  '×+-⌹'⊃⍨ それを使用して、シンボルのリストから選択します*

   実行(シンボルを関数に変換)


÷通常の除算)の代わりに(行列除算)が使用され、空のリストでエラーが発生します。


::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 bytes

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

Readable Version

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)))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.