다항식 계수 계산


27

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

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

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

다항식 계수

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

태스크

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

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

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

  • 모든 코드는 n 및 m의 경우 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]

이 핸들은 최대 입력 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의 미친 듯함에 감동합니다.
— 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+⋯+km−1)


2

Mathematica, 26 바이트

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

예:

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

Out[1]= 1934550571913396675776550070308250

2

파이썬 3, 93 91

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

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 좌측 인수로한다.

{×/⍵!⍺-+\¯1↓0,⍵}

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

{… } 익명의 람다; ⍺왼쪽 인수 ( 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 바이트

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

@(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.