多項係数を計算する


27

すべてが参加できる簡単なチャレンジの時間です!

多項定理の状態: Formula for computing the nth power of a multinomial

括弧内の式は、次のように定義される多項係数です。

Multinomial coefficient

用語が可能にk個のIのすべての整数のパーティション上の範囲にn個与えるNパスカルの番目のレベルM -simplexを。あなたの仕事は、この係数を計算することです。

仕事

m個の数値、nk 1k 2、...、k m-1を取り、対応する多項係数を出力または返すプログラムまたは関数を記述します。プログラムは、必要に応じて、オプションでmを追加の引数として使用できます。k mは入力にないことに注意してください

  • これらの数値は、多項係数の実際の計算がエンコードプロセスではなくコードによって実行される限り、任意の形式で入力できます。たとえば、リストにグループ化されるか、単項でエンコードされるなどです。

  • 出力形式も同様に柔軟です。

  • nおよびmの場合、すべてのコードは1000 分まで1分未満で実行されます。

  • 整数オーバーフローを心配しないでください。

  • 多項係数を計算するために設計された組み込み関数は許可されていません。

  • 標準の抜け穴が適用されます。

得点

これはコードゴルフです。バイト単位の最短ソリューションが勝ちです。

テストケース

Input: 3, [2, 0]
Output: 3

Input: 3, [1, 1]
Output: 6

Input: 11, [1, 4, 4]
Output: 34650

Input: 4, [1,2]
Output: 12

Input: 15, [5,4,3,2]
Output: 37837800

Input: 95, [65,4,4]
Output: 1934550571913396675776550070308250

Input: 32, [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]
Output: 4015057936610313875842560000000

Input: 15, [3,3,3,3]
Output: 168168000

Input: 1000, [10,10,10,10,10,10,10,10,10,10,100,100,100,100,100,100,100,100]
Output: 1892260836114766064839886173072628322819837473493540916521650371620708316292211493005889278395285403318471457333959691477413845818795311980925098433545057962732816261282589926581281484274178579110373517415585990780259179555579119249444675675971136703240347768185200859583936041679096016595989605569764359198616300820217344233610087468418992008471158382363562679752612394898708988062100932765563185864346460326847538659268068471585720069159997090290904151003744735224635733011050421493330583941651019570222984959183118891461330718594645532241449810403071583062752945668937388999711726969103987467123014208575736645381474142475995771446030088717454857668814925642941036383273459178373839445456712918381796599882439216894107889251444932486362309407245949950539480089149687317762667940531452670088934094510294534762190299611806466111882595667632800995865129329156425174586491525505695534290243513946995156554997365435062121633281021210807821617604582625046557789259061566742237246102255343862644466345335421894369143319723958653232683916869615649006682399919540931573841920000000000000

Input: 33, [17]
Output: 1166803110

Input: 55, [28]
Output: 3824345300380220

不正確なエラーはありますか?すなわち、ではなく、1934550571913396675776550070308250出力できます1.9345505719133966e+33か?
コナーオブライエン

@CᴏɴᴏʀO'Bʀɪᴇɴ64ビットの浮動小数点数を使用した場合[1000 {999 ones}]、指数は64ビットの浮動小数点数が表すことができるものをはるかに超えているため、入力をまったく表すことができません。(128ビットの浮動小数点数で十分かもしれませんが、JavaScriptのネイティブの数値型を使用することを前提としていますか?)
Martin Ender

@MartinBüttnerはい、それは正しい仮定です。
コナーオブライエン

2
@quintopia「全員が参加できる別の簡単なチャレンジの時間です!」。私以外のみんな!(パスカルのシンプレックスと多項式がDであるかどうかはわかりませんので)LOL。
アシュウィングプタ

@AshwinGupta心配する必要はありません。2番目の画像の式を計算するだけで、準備完了です!👍
quintopia

回答:


21

ゼリー7 6バイト

;_/!:/

見てください、Unicodeはありません!このプログラムは、最初のインデックスがnである単一のリストを入力として受け取ります。

オンラインでお試しください!または、すべてのテストケースを一度に検証します

使い方

;_/!:/ Input: A (list)

 _/    Reduce A by subtraction. This subtracts all other elements from the first.
;      Concatenate A with the result to the right.
   !   Apply factorial to all numbers in the resulting list.
    :/ Reduce the result by division. This divides the first element by the others.

これは、私が最も単純なものとして考えていたアルゴリズムです。
キントピア

9

CJam、11バイト

l~_:-+:m!:/

n最初に単一のリストとして入力します:

[95 65 4 4]

このハンドルは、最大入力nし、mほとんど瞬時に1000年。

ここでテストしてください。

説明

l~  e# Read a line of input and evaluate it.
_   e# Duplicate.
:-  e# Fold subtraction over the list. A fold is essentially a foreach loop that starts
    e# from the second element. Hence, this subtracts all the k_i from n, giving k_m.
+   e# Append k_m to the list.
:m! e# Compute the factorial of each element in the list.
:/  e# Fold division over the list. Again, this divides n! by each of the k_i!.

あなたは実際にバイトカウントの競争に負けるように見えますが、私はCJamの非常識な簡潔さに感銘を受けていると言わざるを得ません。
16年

@phord Well CJamはJelly(またはPyth)にはマッチしません。しかし、私はそれがどれだけコンパクトになってしまったのか自分自身に非常に驚きました。私の最初のソリューションは21バイトでしたが、最適とは思えませんでしたが、半分に削減できるとは思いませんでした。
マーティンエンダー

4

MATL、21 15バイト

対数ガンマ関数を有効に活用しましょう。これは、階乗自体ではなく階乗の対数を処理することにより、内部オーバーフローを回避します。

1+ZgiO$Gs-h1+Zgs-ZeYo

これは言語/コンパイラの現在のバージョン(9.2.2)で機能しますが、これはこの課題よりも前のものです。

入力は、最初に数値、次に数値ベクトルです。結果はaとして生成され、double最大出力はどこかに制限され2^52ます。

>> matl 1+ZgiO$Gs-h1+Zgs-ZeYo
> 15
> [5 4 3 2]
37837800

説明

1+       % implicit input (number). Add 1
Zg       % log-gamma function
i        % input (numeric vector).
0$G      % push both inputs
s-       % sum the second input (vector) and subtract from first
h1+      % append to vector. Add 1
Zg       % log-gamma function, element-wise on extended vector
s        % sum of results
-        % subtract from previous result of log-gamma
Ze       % exponential
Yo       % round. Implicit display

4
オンラインでお試しください!現在、実験的なMATLサポートがあります:matl.tryitonline.net/…提案を歓迎します。
デニス

1
@Dennis Hey!驚いた!!!どうすれば感謝できますか?私は提案があります:あなたがマドリードに来たなら、私はあなたにおいしい夕食といくつかの飲み物を借りる必要があります
ルイス・メンドー

本当に感謝しています。オンラインで入手できてうれしいです。リビジョンをどのように処理しますか?私はまだ絶えず...あなたが知っている、言語を更新しています
ルイスMendo

今のところ、私は手動でインタープリターを更新しています。更新を行う場合は、The Nineteenth Byteでpingしてください。すぐにプルします。-近い将来マドリードに行かなければならないので、あなたの申し出を心に留めておきます。;)
デニス

@Dennis素晴らしい!そうすれば、直接会うことができます!
ルイスメンドー

4

PowerShell、91 74バイト

わー!PPCGに関する私の100番目の答え!

param($n,$k)(1..$n-join'*'|iex)/(($k|%{$n-=$_;1..$_})+(1..$n)-join'*'|iex)

ふう 最短コードを獲得するつもりはありません、それは確かです。ただし、範囲でいくつかの巧妙なトリックを使用します。そして、これはおそらく、PowerShellに慣れていない人にとっては完全に意味不明です。

説明

まず、入力を受け取り、配列であるparam($n,$k)と想定$kします.\compute-the-multinomial-coefficient.ps1 11 @(1,4,4)

分子(の左側すべて)から始めます/。それは単に範囲です1..$nされていること-joinと一緒ED *、その後で評価iex(すなわち、階乗を計算します1*2*3*...*$n)。

次に、我々をループ$k|%{...}し、各繰り返し、私たちは現在の値を減算$_から$n定式化するために(私たちはもう気にしない)$k_m以降。さらに、1..$k_i各反復ごとに範囲を生成し、パイプラインに残します。これらのパイプラインオブジェクトは、2番目の式range 1..$n$k_mこの時点で)で配列連結されます。これらはすべて、分子と同様にと-join一緒に最終的にed *で評価されますiex(これはで動作するためx! * y! = 1*2*3*...*x * 1*2*3*...*y、個々の順序については気にしません)。

最後に、/分子が分母で除算されて出力されます。

変数を特定のデータ型として明示的にキャストしていないため、より大きな数値の出力を正しく処理します。そのため、PowerShellは必要に応じてオンザフライで異なるデータ型として静かに再キャストします。数値が大きい場合は、データ型の再キャスト時に有効数字を最もよく保持するための科学表記法による出力。たとえば、.\compute-the-multinomial-coefficient.ps1 55 @(28)が出力されます3.82434530038022E+15。私は与えられ、これがOKであることを前提だ「出力形式も同様に柔軟であるが、」挑戦とquintopiaのコメントで指定されている最終的な結果は、ネイティブタイプINTEGERサポート内に収まることができれば、結果は正確でなければならない」。それができない場合は、そこに出力されるものに制限はありません。」


代わりに

出力フォーマットの決定に応じて、92バイトの次のもの

param($n,$k)((1..$n-join'*'|iex)/(($k|%{$n-=$_;1..$_})+(1..$n)-join'*'|iex)).ToString('G17')

上記と同じですが、明示的な出力フォーマットを使用し.ToString('G17')て、必要な桁数を実現します。この55 @(28)ために出力されます3824345300380220.5


Edit1-削除し$dて直接計算することで17バイトを節約し、 Edit2 $k_mをループしている間に$k
文字列化することで計算を削除する-明示的なフォーマットの代替バージョンを追加しました


3

APL(Dyalog Extended)、9バイト

×/2!/+\⍛,

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

Using the idea from my APL answer on another challenge that involves multinomials.

A tacit function whose left argument is the list of k's, and right argument is n. The test cases check if it agrees with Adam's solution with left and right arguments flipped.

How it works

×/2!/+\⍛,
     +\     Cumulative sum of k's (up to m-1'th element)
       ⍛,   Append n (sum of k_1 to k_m)
  2!/       Binomial of consecutive pairs
×/          Product

(k1+k2++km)!k1!k2!km!=(k1+k2)!k1!k2!×(k1+k2++km)!(k1+k2)!k3!km!

=(k1+k2)!k1!k2!×(k1+k2+k3)!(k1+k2)!k3!×(k1+k2++km)!(k1+k2+k3)!km!

==(k1+k2k1)(k1+k2+k3k1+k2)(k1++kmk1++km1)


2

Mathematica, 26 bytes

#!/Times@@({#-+##2,##2}!)&

Example:

In[1]:= #!/Times@@({#-+##2,##2}!)&[95,65,4,4]

Out[1]= 1934550571913396675776550070308250

2

Python 3, 93 91

Thanks to Dennis and FryAmTheEggman.

f=lambda x:0**x or x*f(x-1)
def g(n,k):
    r=f(n)
    for i in k:r//=f(i)
    return r//f(n-sum(k))

n as integer, k as iterable.

Ungolfed:

import functools #cache

@functools.lru_cache(maxsize=None) #cache results to speed up calculations
def factorial(x):
    if x <= 1: return 1
    else: return x * factorial(x-1)

def multinomial(n, k):
    ret = factorial(n)
    for i in k: ret //= factorial(i)
    km = n - sum(k)
    return ret//factorial(km)

1
You can use a single space instead of four for the dynamic whitespace bit
Conor O'Brien

I used tabs, they got replaced in this post. Byte count seems to be OK. I'm not sure about float result and possible overflow.
Trang Oul

2
1. This produces an incorrect for 95, [65, 4, 4]. Note that the input does not contain k_m. 2. You don't seem to be using from functools import* at all.
Dennis

2
1. Your golfed code doesn't use reduce. 2. import math;f=math.factorial saves a byte. 3. Python 2 would allow you to get rid of the second / in //.
Dennis

1
Defining f on your own saves some bytes: f=lambda x:0**x or x*f(x-1).
FryAmTheEggman

2

APL (Dyalog Unicode), 16 bytesSBCS

Entirely based on the mathematical skill of my colleague Marshall.

Anonymous infix function. Takes k as right argument and n as left argument.

{×/⍵!⍺-+10,⍵}

Try it online!

{} anonymous lambda; is left argument (n) and is right argument (k)

0,⍵ prepend a zero to k

¯1↓ drop the last item from that

+\ cumulative sum of that

⍺- subtract that from n

⍵! (k) that

×/ product of that


1

PARI/GP, 43 bytes

Pretty straightforward; aside from formatting, the ungolfed version might well be identical.

m(n,v)=n!/prod(i=1,#v,v[i]!)/(n-vecsum(v))!

1

Matlab 48 bytes

You need to set format to long in advance to get the higher precision. Then, it's quite straightforward:

@(n,k)factorial(n)/prod(factorial([k,n-sum(k)]))

ans(95, [65,4,4])
ans =

 1.934550571913395e+33

1

Pyth, 10 bytes

/F.!MaQ-FQ

Try it online: Demonstration

Explanation:

/F.!MaQ-FQ   implicit: Q = input list
       -FQ   reduce Q by subtraction
     aQ      append the result to Q
  .!M        compute the factorial for each number
/F           reduce by division

1

J, 16 bytes

[(%*/)&:!],(-+/)

Usage

For larger values, a suffix of x is used to denote extended precision integers.

   f =: [(%*/)&:!],(-+/)
   11 f 1 4 4
34650
   15x f 5 4 3 2
37837800

Explanation

[(%*/)&:!],(-+/)  Input: n on LHS, A on RHS
             +/   Reduce A using addition
            -     Subtract that sum from n, this is the missing term
         ]        Get A
          ,       Append the missing term to A to make A'
[                 Get n
      &:!         Take the factorial of n and each value in A'
   */             Reduce using multiplication the factorials of A'
  %               Divide n! by that product and return

1

05AB1E, 8 bytes

Ƹ«!R.«÷

Try it online! Explanation:

Æ           Subtract all the elements from the first
 ¸«         Append to the original list
   !        Take the factorial of all the elements
    R.«÷    Reduce by integer division

I can't seem to find better ways of performing step 2 or step 4.




0

Clojure, 70 bytes

#(let[a apply](a /(map(fn[x](a *(map inc(range x))))(conj %(a - %)))))

Creates an anonymous function taking all of the arguments as a single list, with n first.

30 characters are "wasted" just defining the damn factorial function. Oh well.


0

Perl 6,  52  50 bytes

->\n,\k{[*](1..n)div[*] ([*] 1..$_ for |k,[-] n,|k)}

Test it

->\n,\k{[*](1..n)/[*] ([*] 1..$_ for |k,[-] n,|k)}

Test it (result is a Rational with denominator of 1)

Expanded:

->     # pointy block lambda
  \n,
  \k
{
    [*]( 1 .. n )   # factorial of 「n」

  /                 # divide (produces Rational)

    [*]             # reduce the following using &infix:«*»

      (
          [*] 1..$_ # the factorial of

        for         # each of the following

          |k,       # the values of 「k」 (slipped into list)
          [-] n,|k  # 「n」 minus the values in 「k」
      )
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.