Tính hệ số đa cực


27

Thời gian cho một thử thách dễ dàng khác trong đó tất cả có thể tham gia!

Định lý đa cực cho biết: Công thức tính toán sức mạnh thứ n của đa thức

Biểu thức trong ngoặc là hệ số đa thức, được định nghĩa là:

Hệ số đa cực

Việc cho phép các thuật ngữ k i phạm vi trên tất cả các phân vùng số nguyên của n sẽ cung cấp cấp thứ n của m -simplex của Pascal . Nhiệm vụ của bạn là tính toán hệ số này.

Bài tập

Viết chương trình hoặc hàm lấy m số, n , k 1 , k 2 , ..., k m - 1 và xuất hoặc trả về hệ số đa thức tương ứng. Chương trình của bạn có thể tùy chọn lấy m làm đối số bổ sung nếu cần. Lưu ý rằng k m không có trong đầu vào.

  • Các số này có thể được nhập theo bất kỳ định dạng nào mà một lượt thích, ví dụ được nhóm thành các danh sách hoặc được mã hóa theo dạng đơn nhất hoặc bất cứ thứ gì khác, miễn là tính toán thực tế của hệ số đa phương thức được thực hiện bởi mã của bạn chứ không phải quá trình mã hóa.

  • Định dạng đầu ra là linh hoạt tương tự.

  • Tất cả các mã sẽ chạy trong ít hơn một phút cho nm lên đến 1000.

  • Đừng lo lắng về tràn số nguyên.

  • Không được phép xây dựng để tính toán hệ số đa cực.

  • Tiêu chuẩn áp dụng.

Chấm điểm

Đây là mã golf: Giải pháp ngắn nhất trong byte thắng.

Các trường hợp thử nghiệm

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

Chúng ta có thể có lỗi không chính xác? Tức là, thay vì 1934550571913396675776550070308250, chúng ta có thể đầu ra 1.9345505719133966e+33?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Nếu bạn đã sử dụng số float 64 bit, bạn hoàn toàn không thể đại diện cho đầu vào [1000 {999 ones}], bởi vì số mũ vượt xa những gì số float 64 bit có thể đại diện. (Số float 128 bit có thể sẽ đủ, nhưng tôi giả sử bạn muốn sử dụng loại số gốc của JavaScript?)
Martin Ender

@ MartinBüttner Vâng, đó là một giả định chính xác.
Conor O'Brien

2
@quintopia "Thời gian cho một thử thách dễ dàng khác mà tất cả đều có thể tham gia!". Tất cả mọi người trừ tôi! (Vì tôi không biết Pascals Simplex và multinomials là gì D :) LOL.
Ashwin Gupta

@AshwinGupta Đừng lo lắng về điều đó. Bạn chỉ cần tính toán biểu thức trong hình ảnh thứ hai và bạn tốt để đi! 👍
quintopia

Câu trả lời:


21

Thạch , 7 6 byte

;_/!:/

Nhìn ma, không có Unicode! Chương trình này lấy một danh sách làm đầu vào, với n ở chỉ mục đầu tiên.

Hãy thử trực tuyến! hoặc xác minh tất cả các trường hợp thử nghiệm cùng một lúc .

Làm thế nào nó hoạt động

;_/!:/ 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.

Đây là khá nhiều thuật toán tôi có trong đầu là đơn giản nhất.
quintopia

9

CJam, 11 byte

l~_:-+:m!:/

Nhập dưới dạng một danh sách với nđầu tiên:

[95 65 4 4]

Xử lý này đầu vào lên đến nm1000 khá nhiều ngay lập tức.

Kiểm tra nó ở đây.

Giải trình

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

Có vẻ như bạn thực sự sẽ thua cuộc cạnh tranh đếm byte, nhưng tôi phải nói rằng tôi rất ấn tượng với sự căng thẳng điên rồ của CJam.
phord

@phord Vâng, CJam không phù hợp với Jelly (hoặc Pyth cho vấn đề đó). Nhưng tôi khá ngạc nhiên khi thấy nó nhỏ gọn như thế nào. Giải pháp đầu tiên của tôi có 21 byte và trong khi nó có vẻ không tối ưu, tôi không nghĩ rằng tôi gần như có thể cắt nó xuống một nửa.
Martin Ender

4

MATL , 21 15 byte

Hãy sử dụng chức năng log-gamma để sử dụng tốt. Điều này tránh tràn nội bộ bằng cách làm việc với logarit của giai thừa, chứ không phải với giai thừa.

1+ZgiO$Gs-h1+Zgs-ZeYo

Điều này hoạt động trong phiên bản hiện tại (9.2.2) của ngôn ngữ / trình biên dịch, sớm hơn thử thách này.

Đầu vào là: đầu tiên là một số, sau đó là một vectơ số. Kết quả được tạo ra như một double, giới hạn đầu ra tối đa ở đâu đó xung quanh2^52 .

Thí dụ

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

Giải trình

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
Hãy thử trực tuyến! hiện có hỗ trợ MATL thử nghiệm: matl.tryitonline.net/ Đề xuất được chào đón.
Dennis

1
@Dennis Này! Thật ngạc nhiên!!! Làm thế nào tôi có thể cảm ơn bạn ?? Tôi có một gợi ý: nếu bạn từng đến Madrid, tôi nợ bạn một bữa tối ngon miệng và một số đồ uống
Luis Mendo

Tôi thực sự biết ơn. Thật tuyệt khi có nó trực tuyến. Làm thế nào chúng ta sẽ xử lý sửa đổi? Tôi vẫn liên tục cập nhật ngôn ngữ, bạn biết đấy ...
Luis Mendo

Hiện tại, tôi đang cập nhật thủ công các thông dịch viên. Nếu bạn thực hiện cập nhật, chỉ cần ping tôi trong The Nineteenth Byte và tôi sẽ kéo nó càng sớm càng tốt. - Tôi sẽ phải đến Madrid trong tương lai gần, vì vậy tôi sẽ ghi nhớ lời đề nghị của bạn. ;)
Dennis

@Dennis Tuyệt vời! Bằng cách đó chúng ta có thể gặp nhau trực tiếp!
Luis Mendo

4

PowerShell, 91 74 byte

Woo! Câu trả lời thứ 100 của tôi về PPCG!

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

Phù Sẽ không giành được mã ngắn nhất, đó là điều chắc chắn. Tuy nhiên, sử dụng một vài thủ thuật gọn gàng với các phạm vi. Và điều này có lẽ hoàn toàn vô nghĩa đối với bất kỳ ai không quen thuộc với PowerShell.

Giải trình

Đầu tiên chúng ta lấy đầu vào với param($n,$k)và dự kiến $klà một mảng, vd .\compute-the-multinomial-coefficient.ps1 11 @(1,4,4).

Chúng ta sẽ bắt đầu với tử số (mọi thứ ở bên trái /). Đó chỉ đơn giản là một phạm vi từ 1..$nđó đã được chỉnh sửa -joincùng với *và sau đó được đánh giá iexđể tính giai thừa (nghĩa là1*2*3*...*$n ).

Tiếp theo, chúng tôi lặp lại $k|%{...}và mỗi lần lặp chúng tôi trừ đi giá trị hiện tại $_từ $n(mà chúng tôi không quan tâm nữa) để xây dựng $k_msau. Ngoài ra, chúng tôi tạo ra phạm vi 1..$k_imỗi lần lặp, được để lại trên đường ống. Các đối tượng đường ống đó được nối với mảng với biểu thức thứ hai, phạm vi 1..$n(nằm $k_mở điểm này). Tất cả điều đó là cuối cùng -joined cùng với *và đánh giá với iex, tương tự như các tử số (vì tác phẩm nàyx! * y! = 1*2*3*...*x * 1*2*3*...*y , vì vậy chúng tôi không quan tâm đến đặt hàng cá nhân).

cuối cùng / xảy ra, tử số được chia cho mẫu số và đầu ra.

Xử lý đầu ra chính xác cho số lượng lớn hơn, vì chúng tôi không truyền rõ ràng bất kỳ biến nào như bất kỳ kiểu dữ liệu cụ thể nào, vì vậy PowerShell sẽ âm thầm truyền lại dưới dạng các kiểu dữ liệu khác nhau khi cần. Đối với số lượng lớn hơn, đầu ra thông qua ký hiệu khoa học để bảo toàn tốt nhất các số liệu quan trọng khi các kiểu dữ liệu được truyền lại. Ví dụ, .\compute-the-multinomial-coefficient.ps1 55 @(28)sẽ xuất ra 3.82434530038022E+15. Tôi cho rằng điều này sẽ ổn khi được đưa ra "Định dạng đầu ra linh hoạt tương tự" được chỉ định trong nhận xét và thách thức của quintopia "Nếu kết quả cuối cùng có thể phù hợp với các loại số nguyên được hỗ trợ, thì kết quả phải chính xác. không hạn chế những gì có thể là đầu ra. "


Hoặc

Tùy thuộc vào các quyết định định dạng đầu ra, sau đây là 92 byte

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

Giống như ở trên, chỉ cần sử dụng định dạng đầu ra rõ ràng với .ToString('G17')để đạt được số chữ số mong muốn. Đối với 55 @(28)điều này sẽ xuất3824345300380220.5


Edit1 - Đã lưu 17 byte bằng cách loại bỏ $dvà chỉ cần tính toán trực tiếp và loại bỏ phép tính $k_mbằng cách xâu chuỗi nó trong khi chúng tôi lặp lại $k
Edit2 - Đã thêm phiên bản thay thế với định dạng rõ ràng


3

APL (Dyalog mở rộng) , 9 byte

×/2!/+\⍛,

Hãy thử trực tuyến!

Sử dụng ý tưởng từ câu trả lời APL của tôi cho một thách thức khác liên quan đến đa thức .

Hàm ngầm định có đối số bên trái là danh sách của k và đối số bên phải là n. Các trường hợp kiểm tra kiểm tra xem nó có đồng ý với giải pháp của Adam với các đối số trái và phải được lật không.

Làm thế nào nó hoạt động

×/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

Toán học, 26 byte

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

Thí dụ:

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

Out[1]= 1934550571913396675776550070308250

2

Con trăn 3, 93 91

Cảm ơn 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))

nnhư số nguyên, knhư lặp đi lặp lại.

Ung dung:

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
Bạn có thể sử dụng một khoảng trắng thay vì bốn cho bit khoảng trắng động
Conor O'Brien

Tôi đã sử dụng các tab, họ đã thay thế trong bài viết này. Số lượng byte dường như là OK. Tôi không chắc chắn về kết quả nổi và có thể tràn.
Trang Oul

2
1. Điều này tạo ra một không chính xác cho 95, [65, 4, 4]. Lưu ý rằng đầu vào không chứa k_m . 2. Bạn dường như không sử dụng from functools import*gì cả.
Dennis

2
1. Mã đánh gôn của bạn không sử dụng reduce. 2. import math;f=math.factoriallưu một byte. 3. Python 2 sẽ cho phép bạn để thoát khỏi thứ hai /trong //.
Dennis

1
Xác định ftrên của riêng bạn tiết kiệm một số byte : f=lambda x:0**x or x*f(x-1).
FryAmTheEggman

2

APL (Dyalog Unicode) , 16 byte SBCS

Hoàn toàn dựa trên kỹ năng toán học của đồng nghiệp Marshall của tôi .

Hàm infix ẩn danh. Lấy k là đối số phải và n là đối số trái.

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

Hãy thử trực tuyến!

{... } lambda vô danh; là đối số trái ( n ) và là đối số phải ( k )

0,⍵ trả trước từ 0 đến k

¯1↓ bỏ mục cuối cùng từ đó

+\ tổng tích lũy của điều đó

⍺- trừ đi từ n

⍵! ( k )

×/ sản phẩm đó


1

PARI / GP, 43 byte

Khá đơn giản; ngoài định dạng, phiên bản không được chỉnh sửa có thể giống hệt nhau.

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

1

Matlab 48 byte

Bạn cần phải thiết lập formatđể longtrước để có được độ chính xác cao hơn. Sau đó, nó khá đơn giản:

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

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

 1.934550571913395e+33

1

Bình thường, 10 byte

/F.!MaQ-FQ

Dùng thử trực tuyến: Trình diễn

Giải trình:

/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 byte

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

Sử dụng

Đối với các giá trị lớn hơn, hậu tố xđược sử dụng để biểu thị các số nguyên chính xác mở rộng.

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

Giải trình

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

Ƹ«!R.«÷

Hãy thử trực tuyến! Giải trình:

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

Tôi dường như không thể tìm thấy những cách tốt hơn để thực hiện bước 2 hoặc bước 4.




0

Clojure, 70 byte

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

Tạo một hàm ẩn danh lấy tất cả các đối số làm một danh sách, với n đầu tiên.

30 ký tự bị "lãng phí" khi chỉ xác định hàm giai thừa chết tiệt. Ồ tốt


0

Perl 6 ,  52  50 byte

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

Kiểm tra nó

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

Kiểm tra nó (kết quả là một Rational với mẫu số là 1)

Mở rộng:

->     # 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」
      )
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.