다항식 계수 계산


27

모두가 참여할 수있는 또 다른 쉬운 도전을위한 시간입니다!

다항식 정리는 다음과 같이 말합니다. 다항식의 n 제곱을 계산하기위한 공식

괄호 안의 표현은 다항식 계수로 다음과 같이 정의됩니다.

다항식 계수

조건이 허용 케이 내가 모두 정수 파티션 위에 범위 n은 제공 N 파스칼 번째 레벨의 m -simplex한다. 당신의 임무는이 계수를 계산하는 것입니다.

태스크

m 숫자 n , k 1 , k 2 , ..., k m-1 을 취하여 해당 다항식 계수를 출력하거나 반환 하는 프로그램 또는 함수를 작성하십시오 . 필요한 경우 프로그램이 선택적 으로 추가 인수로 m 을 사용할 수 있습니다. 참고 케이 m은 입력에서 아니다.

  • 다항식 계수의 실제 계산이 인코딩 프로세스가 아닌 코드에 의해 수행되는 한, 이러한 숫자는 원하는 형식으로 입력 될 수 있습니다 (예 : 목록으로 그룹화되거나 단항으로 인코딩 됨)

  • 출력 형식도 비슷합니다.

  • 모든 코드는 nm의 경우 1 분 이내에 최대 1000까지 실행해야합니다 .

  • 정수 오버플로에 대해 걱정하지 마십시오.

  • 다항 계수를 계산하도록 설계된 내장 기능은 허용되지 않습니다.

  • 표준 허점이 적용됩니다.

채점

이것은 코드 골프입니다 : 바이트 단위의 최단 솔루션이 승리합니다.

테스트 사례

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있습니까?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ 64 비트 부동 소수점을 사용하는 경우 [1000 {999 ones}]지수는 64 비트 부동 소수점이 나타낼 수있는 것 이상의 방법이므로 입력 을 전혀 표현할 수 없습니다 . (128 비트 플로트이면 충분하지만 JavaScript의 기본 숫자 유형을 사용한다고 가정합니까?)
Martin Ender

@ MartinBüttner 네, 맞습니다.
코너 오브라이언

2
@quintopia "모두가 참여할 수있는 또 다른 쉬운 도전을위한 시간입니다!". 나를 제외한 모두! (나는 파스칼 심플 렉스와 다항식이 D인지 모릅니다.) LOL.
Ashwin Gupta

@AshwinGupta 걱정하지 마십시오. 두 번째 이미지에서 표현식을 계산하면 좋습니다. 👍
quintopia

답변:


21

젤리 , 7 6 바이트

;_/!:/

유니 코드가없는 엄마! 이 프로그램은 첫 번째 색인에서 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.

이것은 내가 생각했던 가장 간단한 알고리즘입니다.
quintopia

9

CJam, 11 바이트

l~_:-+:m!:/

n먼저 단일 목록으로 입력하십시오 .

[95 65 4 4]

이 핸들은 최대 입력 nm거의 즉시 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의 미친 듯함에 감동합니다.
phord

@phord Well CJam은 Jelly (또는 Pyth)와 일치하지 않습니다. 그러나 나는 그것이 얼마나 컴팩트했는지 스스로 놀랐습니다. 첫 번째 솔루션에는 21 바이트가 있었고 최적으로는 보이지 않지만 거의 반으로자를 수 있다고 생각하지 않았습니다.
Martin Ender

4

MATL , 21 15 바이트

로그 감마 기능 을 잘 활용 합시다 . 이것은 계승 자체가 아닌 계승의 로그로 작업하여 내부 오버플로를 방지합니다.

1+ZgiO$Gs-h1+Zgs-ZeYo

이것은 언어 / 컴파일러의 현재 버전 (9.2.2) 에서 작동 하며이 문제보다 빠릅니다.

입력은 먼저 숫자와 숫자 벡터입니다. 결과는로 생성되어 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/… 제안은 환영합니다.
Dennis

1
트윗 담아 가기 놀랐는 걸!!! 어떻게 감사합니까? 나는 제안을한다 : 만약 당신이 마드리드에 온다면 나는 당신에게 좋은 저녁 식사와 약간의 음료를 빚졌다
Luis Mendo

정말 고마워요 온라인으로하는 것이 좋습니다. 개정은 어떻게 처리합니까? 나는 여전히 언어를 계속 업데이트하고 있습니다.
Luis Mendo

지금은 통역사를 수동으로 업데이트하고 있습니다. 업데이트를한다면, The Nineteenth Byte에 나를 핑 (ping)하면 최대한 빨리 가져옵니다. -가까운 시일 내에 마드리드에 가야하므로 제안을 명심하겠습니다. ;)
Dennis

트윗 담아 가기 그렇게하면 직접 만나게됩니다!
Luis Mendo

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와 함께 에드 *다음으로 평가 iex계승을 계산하기 위해 (즉, 1*2*3*...*$n).

다음으로 $k|%{...}반복하고 각 반복마다 현재 값 $_을 빼고 $n(더 이상 신경 쓰지 않음) $k_m나중에 공식화 합니다. 또한 1..$k_i각 반복 범위를 생성 하여 파이프 라인에 남습니다. 이러한 파이프 라인 객체는 두 번째 표현식 인 range 1..$n( $k_m이 시점에 있음)로 배열로 연결됩니다 . 그 모든 것은 분자와 비슷하게 최종적으로 -join와 함께 *평가되고 평가됩니다 iex(이것은 작동하므로 x! * y! = 1*2*3*...*x * 1*2*3*...*y개별 주문에 신경 쓰지 않습니다).

마지막으로 /분자가 분모로 나뉘어 출력됩니다.

변수를 특정 데이터 유형으로 명시 적으로 캐스팅하지 않기 때문에 더 큰 숫자에 대한 출력을 올바르게 처리하므로 PowerShell은 필요에 따라 즉시 다른 데이터 유형으로 자동 다시 캐스팅합니다. 숫자가 클수록 과학적 표기법을 통한 출력은 데이터 유형이 다시 캐스팅 될 때 중요한 수치를 가장 잘 보존합니다. 예를 .\compute-the-multinomial-coefficient.ps1 55 @(28)들어을 출력 3.82434530038022E+15합니다. "출력 형식이 비슷하게 유연하다" 는 질문과 퀴 토피아의 설명에 지정된 경우이 값이 정상이라고 가정합니다 . "최종 결과가 기본적으로 지원되는 정수 유형에 맞으면 결과는 정확해야합니다. "출력 될 수있는 것에 제한이 없습니다."


대안 적으로

출력 형식 결정에 따라 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를 반복하는 동안 함께 문자열 화 하여 계산을 제거하여 17 바이트를 절약 했습니다.$k


3

APL (Dyalog Extended) , 9 바이트

×/2!/+\⍛,

온라인으로 사용해보십시오!

다항식과 관련된 또 다른 문제에 대한 나의 APL의 대답을 사용합니다 .

왼쪽 인수가 k의 목록이고 오른쪽 인수가 n 인 암묵 함수. 테스트 사례 는 왼쪽 및 오른쪽 인수가 뒤집힌 Adam의 솔루션 과 일치하는지 확인합니다 .

작동 원리

×/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 바이트

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

예:

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

Out[1]= 1934550571913396675776550070308250

2

파이썬 3, 93 91

DennisFryAmTheEggman 에게 감사합니다 .

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

nk반복 가능한 정수 로.

언 골프 드 :

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
동적 공백 비트에 대해 4 대신 단일 공백을 사용할 수 있습니다.
Conor O'Brien

탭을 사용 했는데이 게시물에서 교체되었습니다. 바이트 수가 정상인 것 같습니다. 플로트 결과와 가능한 오버플로에 대해 잘 모르겠습니다.
Trang Oul

2
1.에 대해 잘못된 내용을 생성합니다 95, [65, 4, 4]. 입력에 k_m이 포함되어 있지 않습니다 . 2. 당신은 전혀 사용하지 않는 것 같습니다 from functools import*.
Dennis

2
1. 귀하의 골프 코드는를 사용하지 않습니다 reduce. 2. import math;f=math.factorial바이트를 저장합니다. 3. Python 2는에서 두 번째 /를 제거 할 수 있습니다 //.
Dennis

1
정의 f직접하는 것은 일부 바이트를 저장 : f=lambda x:0**x or x*f(x-1).
FryAmTheEggman

2

APL (Dyalog Unicode) , 16 바이트 SBCS

내 동료 Marshall 의 수학적 기술을 완전히 기반으로합니다 .

익명의 접사 기능. 취하고 K 오른쪽 인자와 같은 N 좌측 인수로한다.

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

온라인으로 사용해보십시오!

{} 익명의 람다; 왼쪽 인수 ( n )이고 오른쪽 인수 ( k )입니다.

0,⍵k  앞에 0을 붙이다

¯1↓ 마지막 항목을 삭제

+\ 그 누적 합계

⍺-n  에서 빼기

⍵! ( k )

×/ 그 제품


1

PARI / GP, 43 바이트

꽤 직설적 인; 형식화를 제외하고 ungolfed 버전은 동일 할 수 있습니다.

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

1

Matlab 48 바이트

당신은 세트로 필요 formatlong높은 정밀도를 얻기 위해 사전에. 그런 다음에는 매우 간단합니다.

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

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

 1.934550571913395e+33

1

Pyth, 10 바이트

/F.!MaQ-FQ

온라인으로 사용해보십시오 : 데모

설명:

/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 바이트

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

용법

더 큰 값의 경우 접미사를 x사용하여 확장 정밀도 정수를 나타냅니다.

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

설명

[(%*/)&:!],(-+/)  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 바이트

Ƹ«!R.«÷

온라인으로 사용해보십시오! 설명:

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

2 단계 또는 4 단계를 수행하는 더 좋은 방법을 찾지 못하는 것 같습니다.




0

클로저, 70 바이트

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

n먼저 모든 인수를 단일 목록으로 사용하는 익명 함수를 만듭니다 .

망할 팩토리얼 함수를 정의하는 것만으로 30 문자가 "폐기"됩니다. 오 잘


0

펄 6 ,  52  50 바이트

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

그것을 테스트

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

테스트 (결과는 분모가 1 인 합리적 임)

넓히는:

->     # 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.