ガンマ関数ゴルフ


17

実数所与tにおける(-10^9,13)(含まない-10^9か、13入力、出力として)Γ(t)としても知られている、ガンマ関数は以下のように定義されます:

ガンマ関数の定義

このタスクを解決するために組み込みのガンマ関数を使用したり、組み込みの数値またはシンボリック積分関数を使用したりすることはできません。出力は、有効数字6桁まで、または10^-6実際の値の範囲内で、指定された値に対する制限の少ない方が正確である必要があります。Pythonの組み込みガンマ関数は、実際の値を決定するために使用されます。あなたΓ(t)は定義されていると仮定することができます-つまりt、正の実数または非整数の負の実数-とその|Γ(t)| ≤ 10^9。Pythonの組み込みガンマ関数を使用して、実際の値を取得するために使用できる参照プログラムを次に示します。

1 -> 1.000000
-2.5 -> -0.945309
3.14159265 -> 2.288038
-2.71828182846 -> -0.952682
12 -> 39916800.000000
0.5 -> 1.772454
8.675309 -> 20248.386956
-10.1 -> -0.000002

ルール

  • これはであるため、最短の回答(バイト単位)が優先されます。
  • 標準的な抜け穴は禁止されています。
  • 入力および出力は、言語の標準と見なされる方法で実行できます。
  • 完全なプログラム、関数、または通常あなたの言語にとって有効な答えと考えられるものを書くことができます

リーダーボード

この投稿の下部にあるスタックスニペットは、a)言語ごとの最短ソリューションのリストとして、およびb)リーダーボード全体としての回答からリーダーボードを生成します。

回答が表示されるようにするには、次のマークダウンテンプレートを使用して、見出しから回答を開始してください。

## Language Name, N bytes

N提出物のサイズはどこですか。スコアを改善する場合、古いスコアを打つことで見出しに残すことができます。例えば:

## Ruby, <s>104</s> <s>101</s> 96 bytes

ヘッダーに複数の数字を含める場合(たとえば、スコアが2つのファイルの合計であるか、インタープリターフラグペナルティーを個別にリストする場合)、実際のスコアがヘッダーの最後の数字であることを確認します。

## Perl, 43 + 2 (-p flag) = 45 bytes

言語名をリンクにして、スニペットに表示することもできます。

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


1
| gamma(t)| <10 ^ 9
flawr

リンクは参照実装ではありません
...-sergiol

言い換えそれ@sergiol
MEGO

回答:


2

Pyth、21バイト

TI-BASICの答えと同様に、8 ^ 10の完全な反復でこれをテストすることはできませんでしたが、小さなケースではすべてうまくいくようです。

cu*Gc^hc1HQhcQHS^8T1Q

説明:

                            [implicit: Q=input]
                ^8T         8**10
               S^8T         [1,2,3,...,8**10]
  *Gc^hc1HQhcQH             lambda G,H:G*(1+1/H)**Q/(1+Q/H)
                   1        Base case
 u*Gc^hc1HQhcQHS^8T1        Reduce with base case 1
c                   Q       Divide by Q

それを試してみてください、ここで 2000回の繰り返しの代わりに、8 ^ 10で。


10

C ++ 14、86 85 81バイト

[](auto t){auto v=1.;for(int x=1;x<1e9;++x)v*=pow(1+1./x,t)/(1+t/x);return v/t;};

これにはあまり時間をかけませんでした。実装が最も簡単だと思われる近似を(バイトの形で)見ました。値の計算には時間がかかります(ループはすべての正の整数で行われるため)が、チャレンジでは時間制限が指定されていません。これは、匿名関数(ラムダ)であり、任意の引数( T、その上にpow(double, T)してoperator/(T,int)呼び出すことができます)とリターンをdouble

使い方に追われていない

#include <iostream>
int main()
{
    auto r = [](auto t)
    {
        auto v = 1.;
        for (int x = 1; x < 1e9; ++x)
            v *= pow(1 + 1. / x, t) / (1 + t / x);
        return v / t;
    };
    std::cout << r(-2.71828182846); // outputs -0.952682
}

@Megoもちろんです!ありがとう。
ゼレゲス

-10 ^ 9と10 ^ 9でどのような値が得られますか?あなたが私の賛成票を得る前に、私はまずあなたのものがどれだけうまく機能するかを知りたいです。
flawr

@Mego Microsoftコンパイラは、これらのインクルードのどちらも必要としません。
ゼレゲス

@MegoMicrosoft (R) C/C++ Optimizing Compiler Version 19.00.23026 for x86
Zereges

@flawr Mineプログラムは0を出力しますがgamma(-10e9)、OPには、ガンマ関数が定義されているパラメーターのみを考慮することができます。gamma(10e9)戻りinfながら、Pythonのは、内蔵のガンマ関数は、実際の値が決定するために使用されると言うOverflowError: math range error
Zereges

7

Minkolang 0.1235の 34 25バイト

n$zl8;dz;z$:r[i1+dz+$:*]N

これはエラーで停止します(0で除算しようとすると)が、Meta consensusに従って許可されています。.正常に停止するプログラムの最後にを追加します。すべてのテストケースを一度に試してください。(ループは1e4回しか繰り返されないため、後で終了するよりも早く終了します。)

説明

Zeregesは、代替の無限の製品定義の 1つを使用しました。結局のところ、もう一方はMinkolangでの実装にはるかに適しています。

オイラーのガンマ関数の代替定式化

これは、n無限に向かうときの限界です。つまり、両方n!を計算することができます(t+n)。だから私は1/t(なぜなら0!=1)を取り出します。n^tなぜなら、それはの終了値を知らずに連続して計算できないからnです。たまたま、n制限があるため、2回使用できます。計算の要因として1回、ループを実行する回数として1回。

順次無限積は、通常1で始まる必要があります。この場合、それはn^t/tです。ループの本体では、これを計算k/(t+k)し、これまでの積で乗算します。最後に、製品全体が計算されて出力されました。これは基本的に私のプログラムが行うnことであり、答えが十分に正確であるほど十分に高いものです。

無限製品の爆発バージョン

n                            Take number from input
 $z                          Store it in the register (this is t; retrieved with z)
   l8;                       10^8 (this is n, the limit)
      d                      n,n
       z;                    n,n^t
         z$:                 n,n^t/t
            r                Reverse stack -> n^t/t,n
             [               For loop that runs n times
              i1+            k
                 d           k,k
                  z+         k,t+k
                    $:       k/(t+k)
                      *      Multiply
                       ]N    Close for loop and output as integer

がないので.、折り返して最初からやり直します。ただし、入力が空であるためにn生成さ-1れるようになり、最終的に0で除算しようとしてプログラムが停止します。


5

ジュリア、141バイト

z->(z-=1;a=90;c(k)=(k=big(k);(-1)^(k-1)/factorial(k-1)*(a-k)^(k-.5)*exp(a-k));(z+a)^(z+.5)*exp(-z-a)*(√(2π)+sum([c(k)/(z+k)for k=1:a-1])))

これにより、実数を受け入れて実数を返す名前のないラムダ関数が作成されます。Spoungeの近似を使用しますガンマを計算します。

ゴルフをしていない:

function Γ(z::Real)
    # Spounge's approxmation is for Γ(z+1), so subtract 1
    z -= 1

    # Choose a number for the constant a, which determines the
    # bound on the error
    a = 90

    # Define a function for the sequence c_k
    function c(k::Integer)
        # Convert k to a BigInt
        k = big(k)
        return (-1)^(k-1) / factorial(k-1) * (a-k)^(k-1/2) * exp(a-k)
    end

    # Compute the approximation
    return (z+a)^(z+1/2) * exp(-z-a) * (√(2π) + sum([c(k)/(z+k) for k=1:a-1]))
end

非常に、非常に遅くゴルフが、z->(z-=1;a=90;c(k)=(k=big(k);(-1)^~-k/factorial(k-1)*(a-k)^(k-.5)*exp(a-k));(z+a)^(z+.5)*exp(-z-a)*(√(2π)+sum(c(k)/(z+k)for k=1:a-1)))(少なくともジュリア0.6で)137バイトのために働く必要があります
ミスターXcoder

3

Japt、45バイト

JaptJa vaScri ptの短縮バージョンです。通訳

$for(V=X=1;X<1e9;)$V*=(1+1/X pU /(1+U/X++;V/U

もちろん、1e9 = 1,000,000,000回の反復には永遠に時間がかかるため、テストのために96。(1e6は、有効数字5桁まで正確です。入力で1e8を使用すれ12ば、最初の6個を取得するのに十分です。)

テストケースの結果:(1e7精度を使用)

       1:  1
    -2.5: -0.9453083...
      pi:  2.2880370...
      -e: -0.9526812...
      12:  39916536.5...
     0.5:  1.7724538...
8.675309:  20248.319...
   -10.1: -0.0000022...

使い方

         // Implicit: U = input number
$for(    // Ordinary for loop.
V=X=1;   //  Set V and X to 1.
X<1e9;)$ //  Repeat while X is less than 1e9.
V*=      // Multiply V by:
(1+1/X   //  1 plus (1 over X),
pU /     //  to the power of U, divided by
(1+U/X++ //  1 plus (U over X). Increment X by 1.
;V/U     // Output the result of (V over U).

3

TI-BASIC、35バイト

Input Z
1
For(I,1,ᴇ9
Ans(1+I⁻¹)^Z/(1+Z/I
End
Ans/Z

これはZeregesと同じアルゴリズムを使用します。

警告:実際にこれを完全な1e9反復でテストしていません。値が小さい場合にかかる時間に基づいて、ランタイムは単位になると予想されます。ただし、収束しているように見え、丸め誤差に問題はないはずです。TIは、数値を14桁の精度の10進浮動小数点数として保存します。


あなたはそれをテストしなかったのですか?!
-TanMath

1
@TanMath私はそうしますが、来月の最終試験には計算機が必要です。
リトシアスト

3

Python 3、74 68 78 73バイト

ありがとう@Megoと@xnor

これはZeregesによるC ++回答の翻訳です。基本的に、これはガンマ関数の代替定義であるため、より正確になります(素晴らしいのは、使用するバイト数が少ないことです!)。

すみません、すべての間違いにごめんなさい!

def g(z,v=1):
 for i in range(1,10**9):v*=(1+1/i)**z/(1+z/i)
 return v/z

1
+1あなたが数十億を扱っているときに、範囲には関係ありません。また、これはPython 3であることを指定する必要がありますfrom __future__ import division。Python2のrangeリストを返すという事実に対処するには、浮動小数点除算と数テラバイトのRAMが必要です。さらに、1.0sを1sに置き換えて4を剃ることができます。バイト。
メゴ

2
@TanMath:^xor **ですか、べき乗についてですか?
jermenkoo

3
int(1e9)はただ10**9であり、あなたは周りに括弧を必要としません(1+1/i)**z
-xnor

3

Python、348 448 407 390 389バイト

@Megoに感謝します!

取り消し線448は(ほぼ)まだ448です!:p

これは、Lanzcos近似に基づいています。ここからゴルフ

from cmath import*
C=[0.9999999999998099,676.5203681218851,-1259.1392167224028,771.3234287776531,-17‌6.6150291621406,12.507343278686905,-0.13857109526572012,9.984369578019572e-6,1.5‌​056327351493116e-7]
def g(z):
 z-=1;if z.real<0.5:return pi/(sin(pi*z)*gamma(1-z))
 else:
  x=C[0]
  for i in range(1,9):x+=C[i]/(z+i)
  t=z+7.5;return sqrt(2*pi)*t**(z+0.5)*exp(-t)*x

1
少なくとも、空白(-=の前後のスペースimport *など)を削除し、1文字の関数名を使用して、提出物をゴルフしてください。また、実際の入力のみをサポートする必要があることに注意してください。
リトシアスト

@ThomasKwa編集しました。私の元のバージョンは機能しませんでした。ここに新しいバージョンがあります。
-TanMath

@Mego編集
...-TanMath

これにより、再帰エラーが発生します- z-=1;最初の行のgammaを削除して修正します。また、バイトを節約gammaするgためにに名前を変更し、との名前の競合を避ける必要がありますcmath.gamma。また、余分な先行ゼロを削除します。
Mego

1

ジュリア、41バイト

x->prod([(1+1/i)^x/(1+x/i)for i=1:1E7])/x

これはZeregesのC ++回答の翻訳です。私の他のジュリアの答えはすぐに終わりますが、これはかなり遅いです。私のコンピューターでそれぞれ数秒でテストケースを計算します。

ゴルフをしていない:

function f(x::Real)
    prod([(1 + 1/i)^x / (1 + x/i) for i = 1:1E7]) / x
end

1

プロローグ、114バイト

これはZeregesのC ++回答の翻訳です。

q(F,F,V,Z):-X is V/Z,write(X).
q(F,T,V,Z):-W is(1+1/F)**Z/(1+Z/F)*V,I is F+1,q(I,T,W,Z).
p(N):-q(1.0,1e9,1,N),!.

ここでオンライン試してみてください

p(12).

1e9の再帰で実行するには、約15分かかります。
これを1e6に減らすと、約1秒かかり、テストが簡単になります(ただし精度は低下します)。
あなたのコンピューター/ラップトップ上のインタープリターでそれを実行することは、ほとんどの人にとってもおそらくより高速です。


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