Penentu Matriks Integer

34

Diberikan matriks integer persegi sebagai input, output penentu matriks.

Aturan

  • Anda dapat mengasumsikan bahwa semua elemen dalam matriks, penentu matriks, dan jumlah total elemen dalam matriks berada dalam kisaran integer yang dapat diwakili untuk bahasa Anda.
  • Mengeluarkan nilai desimal / float dengan bagian pecahan 0 diperbolehkan (misalnya, 42.0bukan 42).
  • Builtin diizinkan, tetapi Anda disarankan untuk memasukkan solusi yang tidak menggunakan builtin.

Uji Kasus

[[42]] -> 42
[[2, 3], [1, 4]] -> 5
[[1, 2, 3], [4, 5, 6], [7, 8, 9]] -> 0
[[13, 17, 24], [19, 1, 3], [-5, 4, 0]] -> 1533
[[372, -152, 244], [-97, -191, 185], [-53, -397, -126]] -> 46548380
[[100, -200, 58, 4], [1, -90, -55, -165], [-67, -83, 239, 182], [238, -283, 384, 392]] -> 571026450
[[432, 45, 330, 284, 276], [-492, 497, 133, -289, -28], [-443, -400, 56, 150, -316], [-344, 316, 92, 205, 104], [277, 307, -464, 244, -422]] -> -51446016699154
[[416, 66, 340, 250, -436, -146], [-464, 68, 104, 471, -335, -442], [159, -407, 310, -489, -248, 370], [62, 277, 446, -325, 47, -193], [460, 460, -418, -28, 234, -374], [249, 375, 489, 172, -423, 125]] -> 39153009069988024
[[-246, -142, 378, -156, -373, 444], [186, 186, -23, 50, 349, -413], [216, 1, -418, 38, 47, -192], [109, 345, -356, -296, -47, -498], [-283, 91, 258, 66, -127, 79], [218, 465, -420, -326, -445, 19]] -> -925012040475554
[[-192, 141, -349, 447, -403, -21, 34], [260, -307, -333, -373, -324, 144, -190], [301, 277, 25, 8, -177, 180, 405], [-406, -9, -318, 337, -118, 44, -123], [-207, 33, -189, -229, -196, 58, -491], [-426, 48, -24, 72, -250, 160, 359], [-208, 120, -385, 251, 322, -349, -448]] -> -4248003140052269106
[[80, 159, 362, -30, -24, -493, 410, 249, -11, -109], [-110, -123, -461, -34, -266, 199, -437, 445, 498, 96], [175, -405, 432, -7, 157, 169, 336, -276, 337, -200], [-106, -379, -157, -199, 123, -172, 141, 329, 158, 309], [-316, -239, 327, -29, -482, 294, -86, -326, 490, -295], [64, -201, -155, 238, 131, 182, -487, -462, -312, 196], [-297, -75, -206, 471, -94, -46, -378, 334, 407, -97], [-140, -137, 297, -372, 228, 318, 251, -93, 117, 286], [-95, -300, -419, 41, -140, -205, 29, -481, -372, -49], [-140, -281, -88, -13, -128, -264, 165, 261, -469, -62]] -> 297434936630444226910432057
Mego
sumber
apakah ada ukuran maksimum dari matriks yang perlu didukung atau apakah itu sewenang-wenang?
Taylor Scott
1
@TaylorScott Aturan pertama yang tercantum:You may assume that all elements in the matrix, the determinant of the matrix, and the total number of elements in the matrix are within the representable range of integers for your language.
Mego
4
Anda tahu Anda memiliki tantangan yang menarik ketika Anda memiliki 4 jawaban Jelly berturut-turut di luar golf satu sama lain ...
manusiawi

Jawaban:

25

Jelly , 15 byte

LŒ!ðŒcIṠ;ị"Pð€S

Cobalah online!

Bagaimana itu bekerja

LŒ!ðŒcIṠ;ị"Pð€S   input
L                 length
 Œ!               all_permutations
   ð        ð€    for each permutation:
    Œc                take all unordered pairs
      I               calculate the difference between
                      the two integers of each pair
       Ṡ              signum of each difference
                      (positive -> 1, negative -> -1)
        ;             append:
         ị"             the list of elements generated by taking
                        each row according to the index specified
                        by each entry of the permutation
           P          product of everything
              S   sum

Mengapa ini berfungsi - versi matematika

Operator det mengambil matriks dan mengembalikan skalar. Sebuah n -by- n matriks dapat dianggap sebagai kumpulan n vektor panjang n , sehingga det benar-benar fungsi yang mengambil n vektor dari ℤ n dan kembali skalar.

Karenanya, saya menulis det ( v 1 , v 2 , v 3 , ..., v n ) untuk det [ v 1 v 2 v 3 ... v n ].

Perhatikan bahwa det adalah linear dalam setiap argumen, yaitu det ( v 1 + λ w 1 , v 2 , v 3 , ..., v n ) = det ( v 1 , v 2 , v 3 , ..., v n ) + λ det ( w 1 , v 2 , v 3 , ..., v n ). Oleh karena itu, ini adalah peta linear dari (ℤ n ) n ke ℤ.

Cukuplah untuk menentukan gambar dasar di bawah peta linear. Basis dari (ℤ n ) n terdiri dari n- kali lipat produk tensor dari elemen dasar ℤ n , yaitueg e 5 ⊗ e 3 ⊗ e 1 ⊗ e 5 ⊗ e 1 . Produk tensor yang menyertakan tensor identik harus dikirim ke nol, karena penentu matriks yang dua kolomnya identik adalah nol. Masih untuk memeriksa apa produk tensor dari elemen dasar berbeda dikirim ke. Indeks vektor dalam produk tensor membentuk suatu bijection, yaitu permutasi, di mana permutasi bahkan dikirim ke 1 dan permutasi ganjil dikirim ke -1.

Misalnya, untuk menemukan determinan [[1, 2], [3, 4]]: perhatikan bahwa kolomnya adalah [1, 3] dan [2, 4]. Kami menguraikan [1, 3] untuk memberi (1 e 1 + 3 e 2 ) dan (2 e 1 + 4 e 2 ). Elemen yang sesuai dalam produk tensor adalah (1 e 1 ⊗ 2 e 1 + 1 e 1 ⊗ 4 e 2 + 3 e 2 ⊗ 2 e 1 + 3 e 2 ⊗ 4 e 2 ), yang kami sederhanakan menjadi (2 e 1 ⊗ e 1 + 4 e 1 ⊗ e 2 + 6 e 2 ⊗ e 1 + 12 e 2 ⊗ e 2). Karena itu:

det [[1, 2], [3, 4]]
= det (1 e 1 + 3 e 2 , 2 e 1 + 4 e 2 )
= det (2 e 1 ⊗ e 1 + 4 e 1 ⊗ e 2 + 6 e 2 ⊗ e 1 + 12 e 2 ⊗ e 2 )
= det (2 e 1 ⊗ e 1 ) + det (4 e 1 ⊗ e 2 ) + det (6 e 2 ⊗ e 1 ) + det (12 e 2⊗ e 2 )
= 2 det (e 1 ⊗ e 1 ) + 4 det (e 1 ⊗ e 2 ) + 6 det (e 2 ⊗ e 1 ) + 12 det (e 2 ⊗ e 2 )
= 2 (0) + 4 (1) + 6 (-1) + 12 (0)
= 4 - 6
= -2

Sekarang tetap membuktikan bahwa formula untuk menemukan paritas permutasi adalah valid. Apa yang dilakukan kode saya pada dasarnya adalah menemukan jumlah inversi, yaitu tempat-tempat di mana elemen di sebelah kiri lebih besar daripada elemen di sebelah kanan (tidak harus secara berurutan).

Sebagai contoh, dalam permutasi 3614572, ada 9 inversi (31, 32, 61, 64, 65, 62, 42, 52, 72), sehingga permutasi aneh.

Pembenarannya adalah bahwa setiap transposisi (bertukar dua elemen) baik menambah satu inversi atau menghilangkan satu inversi, menukar paritas jumlah inversi, dan paritas permutasi adalah paritas jumlah transposisi yang diperlukan untuk mencapai permutasi.

Karena itu, sebagai kesimpulan, formula kami diberikan oleh:

Mengapa ini berfungsi - versi non-matematika

di mana σ adalah permutasi dari 𝕊 n kelompok semua permutasi pada n huruf, dan sgn adalah tanda dari permutasi, AKA (-1) diangkat ke paritas permutasi, dan sebuah ij adalah ( ij ) th masuk dalam matriks ( i down, j across).

Biarawati Bocor
sumber
17
"Versi non-matematika" itu benar-benar matematika.
MD XF
6
Rumus dan simbol serta angka @MDXF hampir tidak membentuk matematika. Matematika adalah abstraksi dan generalisasi dan logika di balik manipulasi simbol secara formal.
Leaky Nun
7
@ JAB Jelly mengimplementasikan halaman kode kustom sendiri . (Suatu hari, TIO akan menyertakan tautan ke halaman kode ...)
totallyhuman
1
@Mego "jumlah produk diagonal" hanya berfungsi untuk matriks 1x1, 2x2, dan 3x3. Untuk matriks yang lebih besar, Anda perlu mempertimbangkan semua permutasi dan paritasnya.
Leaky Nun
3
+1 untuk benar - benar menyertakan bukti dalam posting alih-alih mengatakan "karena rumus ini tercantum pada halaman abcxyz itu pasti benar".
user202729
11

R , 3 byte

Solusi Sepele

det

Cobalah online!

R , 94 92 byte

solusi yang diimplementasikan kembali

dikalahkan oleh Jarko Dubbeldam

d=function(m)"if"(x<-nrow(m),m[,1]%*%sapply(1:x,function(y)(-1)^(y-1)*d(m[-y,-1,drop=F])),1)

Cobalah online!

Secara rekursif menggunakan ekspansi oleh anak di bawah umur di kolom pertama dari matriks.

f <- function(m){
 x <- nrow(m)                 # number of rows of the matrix
 if(sum(x) > 1){              # when the recursion reaches a 1x1, it has 0 rows
                              # b/c [] drops attributes
  minor <- function(y){
   m[y] * (-1)^(y-1) *
   d(m[-y,-1])                # recurse with the yth row and first column dropped
   }
  minors <- sapply(1:x,minor) # call on each row
  sum(minors)                 # return the sum
 } else {
  m                           # return the 1x1 matrix
 }
}

Giuseppe
sumber
32 byte
JAD
9

Jelly , 16 15 12 10 byte

Ḣ×Zß-Ƥ$Ṛḅ-

Menggunakan ekspansi Laplace . Terima kasih kepada @miles karena bermain golf 3 5 byte!

Cobalah online!

Bagaimana itu bekerja

Ḣ×Zß-Ƥ$Ṛḅ-  Main link. Argument: M (matrix / 2D array)

Ḣ           Head; pop and yield the first row of M.
      $     Combine the two links to the left into a monadic chain.
  Z         Zip/transpose the matrix (M without its first row).
   ß-Ƥ      Recursively map the main link over all outfixes of length 1, i.e., over
            the transpose without each of its rows.
            This yields an empty array if M = [[x]].
 ×          Take the elementwise product of the first row and the result on the
            right hand. Due to Jelly's vectorizer, [x] × [] yields [x].
       Ṛ    Reverse the order of the products.
        ḅ-  Convert from base -1 to integer.
                [a]          -> (-1)**0*a
                [a, b]       -> (-1)**1*a + (-1)**0*b = b - a
                [a, b, c]    -> (-1)**2*a + (-1)**1*b + (-1)**0*c = c - b + a
                etc.
Dennis
sumber
8

Bahasa Wolfram (Mathematica) , antara 14 dan 42 byte

Kami memiliki solusi built-in 3-byte dan 53-byte yang sepenuhnya menghindari built-in, jadi inilah beberapa solusi aneh di antaranya.

Bahasa Wolfram memiliki banyak fungsi yang sangat intens untuk menguraikan matriks menjadi produk dari matriks lain dengan struktur yang lebih sederhana. Salah satu yang lebih sederhana (artinya saya pernah mendengarnya sebelumnya) adalah dekomposisi Jordan. Setiap matriks mirip dengan matriks segitiga atas (mungkin bernilai kompleks) yang terbuat dari balok diagonal dengan struktur tertentu, yang disebut dekomposisi Jordan dari matriks itu. Kesamaan mempertahankan determinan, dan determinan matriks segitiga adalah produk dari elemen diagonal, sehingga kita dapat menghitung determinan dengan 42 byte berikut :

1##&@@Diagonal@Last@JordanDecomposition@#&

Penentu juga sama dengan produk dari nilai eigen dari sebuah matriks, dengan multiplisitas. Untungnya, fungsi eigenvalue Wolfram melacak multiplisitas (bahkan untuk matriks yang tidak dapat diagonal), jadi kami mendapatkan solusi 20 byte berikut :

1##&@@Eigenvalues@#&

Solusi berikutnya adalah jenis kecurangan dan saya tidak begitu yakin mengapa itu berhasil. Wronskian dari daftar fungsi n adalah penentu matriks turunan n -1 pertama dari fungsi. Jika kita memberi Wronskianfungsi sebuah matriks bilangan bulat dan mengatakan bahwa variabel diferensiasi adalah 1, entah bagaimana ia memuntahkan determinan matriks tersebut. Ini aneh, tetapi tidak melibatkan huruf " Det" dan hanya 14 byte ...

#~Wronskian~1&

(Penentu Casoratian bekerja dengan baik, untuk 1 byte: #~Casoratian~1&)

Di ranah aljabar abstrak, determinan dari suatu n  x  n matriks (dianggap sebagai peta k → k yaitu perkalian dengan determinan) adalah n th kekuatan luar matriks (setelah memetik isomorfisma k → ⋀ n k n ). Dalam bahasa Wolfram, kita bisa melakukan ini dengan 26 byte berikut :

HodgeDual[TensorWedge@@#]&

Dan inilah solusi yang hanya berfungsi untuk penentu positif. Jika kita mengambil unit hypercube n -dimensi dan menerapkan transformasi linear untuknya, "volume" n -dimensi dari wilayah yang dihasilkan adalah nilai absolut dari penentu transformasi. Menerapkan transformasi linear ke kubus memberikan paralelepiped, dan kita dapat mengambil volumenya dengan 39 byte kode berikut:

RegionMeasure@Parallelepiped[Last@#,#]&
Bukan pohon
sumber
1
Solusi yang saya miliki di sepanjang garis ini adalah Exp@*Tr@*MatrixLog, tetapi sayangnya ini tidak bekerja untuk matriks tunggal.
Misha Lavrov
1
@MishaLavrov Ooh, itu pintar! Saya pikir Anda dapat memperbaikinya dengan Check[E^Tr@MatrixLog@#,0]&.
Bukan pohon
Itu keren! Saya belum pernah menyadarinya Checksebelumnya.
Misha Lavrov
1
Saya membuat tantangan untuk Jordan Decomposition beberapa waktu lalu. Anda mungkin tertarik juga. Jawaban yang bagus!
Mego
8

Haskell , 71 byte

-3 byte terima kasih kepada Lynn. Satu lagi bytes debu berkat Craig Roy.

f[]=1
f(h:t)=foldr1(-)[v*f[take i l++drop(i+1)l|l<-t]|(i,v)<-zip[0..]h]

Cobalah online! Menambahkan -Obendera untuk tujuan pengoptimalan. Itu tidak perlu.

Penjelasan (kedaluwarsa)

f secara rekursif mengimplementasikan ekspansi kofaktor.

f[[x]]=x

Baris ini mencakup kasus dasar dari 1 × 1 matriks, dalam hal determinan adalah mat[0, 0].

f(h:t)=

Ini menggunakan pencocokan pola Haskell untuk memecah matriks menjadi kepala (baris pertama) dan ekor (sisa matriks).

          [                                     |(i,v)<-zip[0..]h]

Hitunglah kepala matriks (dengan membuat zip daftar tak terhingga dari bilangan bulat dan kepala) dan beralih di atasnya.

           (-1)*i*v

Meniadakan hasil berdasarkan apakah indeksnya bahkan karena perhitungan faktor penentu melibatkan penambahan dan pengurangan bergantian.

                     [take i l++drop(i+1)l|l<-t]

Ini pada dasarnya menghilangkan kolom ke - i dari ekor dengan mengambil elemen i dan menyatukannya dengan baris dengan elemen pertama (i + 1) yang dijatuhkan untuk setiap baris di ekor.

                   *f

Hitung penentu hasil di atas dan kalikan dengan hasil (-1)*i*v.

       sum

Jumlahkan hasil dari daftar di atas dan kembalikan.

benar-benar manusiawi
sumber
2
Anda bisa menghemat 1 byte jika Anda mengganti sum[(-1)^i*...denganfoldr(-)0[...
Craig Roy
6

Proton , 99 byte

f=m=>(l=len(m))==1?m[0][0]:sum((-1)**i*m[0][i]*f([[m[k][j]for k:1..l]for j:0..l if j-i])for i:0..l)

Cobalah online!

-3 byte terima kasih kepada Tn. Xcoder
-3 byte terima kasih kepada Erik the Outgolfer

Perluasan di baris pertama

HyperNeutrino
sumber
Hanya karena Proton tidak memiliki built-in untuk determinan.
user202729
103 Bytes . ((~i%2)*2-1)->((-i%2)|1)
Tn. Xcoder
Juga 102 byte dengan mengganti j!=idengan j-iatau i-j.
Tn. Xcoder
99 byte
Erik the Outgolfer
@EriktheOutgolfer Ah ya, terima kasih!
HyperNeutrino
5

Oktaf , 28 byte

@(x)round(prod(diag(qr(x))))

Cobalah online!

Ini menggunakan satu QR dekomposisi dari matriks X ke dalam matriks orthgonal Q dan segitiga atas matriks R . Determinan X adalah produk dari orang-orang dari Q dan R . Matriks ortogonal memiliki penentu satuan, dan untuk matriks segitiga penentu adalah produk dari entri diagonal. Oktafqr fungsi yang disebut dengan output tunggal memberikan R .

Hasilnya dibulatkan ke bilangan bulat terdekat. Untuk matriks input besar, ketidaktepatan titik apung dapat menghasilkan kesalahan yang melebihi 0.5dan dengan demikian menghasilkan hasil yang salah.

Luis Mendo
sumber
1
Itu cara yang menarik untuk menghindari detbuiltin. ;)
tommeding
1
@tommeding :-) Juga, sudah "digunakan" dalam jawaban Stewie
Luis Mendo
5

Haskell , 59 byte

p%(l:r)=l!!0*f(tail<$>p++r)-(p++[l])%r
[]%_=1
p%_=0
f=([]%)

Cobalah online!

Tidak
sumber
5

C,  176  125 byte

Terima kasih kepada @ceilingcat untuk bermain golf 42 byte, dan terima kasih kepada @Lynn dan @Jonathan Frech karena telah menghemat setiap byte!

d(M,n)int*M;{int i=n--,s=*M*!n,c,T[n*n];for(;i--;s+=M[i]*(1-i%2*2)*d(T,n))for(c=n*n;c--;T[c]=M[n-~c+c/n+(c%n>=i)]);return s;}

Hitung penentu menggunakan ekspansi Laplace di sepanjang baris pertama.

Cobalah online!

Belum dibuka:

d(M, n)int*M;
{
    int i=n--, s=*M*!n, c, T[n*n];
    for (; i--; s+=M[i]*(1-i%2*2)*d(T,n))
        for (c=n*n; c--;)
            T[c] = M[n-~c+c/n+(c%n>=i)];
    return s;
}
Steadybox
sumber
(i%2*-2+1)(1-i%2*2)menyimpan satu byte lagi.
Lynn
n+1+cbisa n-~c.
Jonathan Frech
Sarankan i=salih-alihreturn s
ceilingcat
5

Jelly , 43 byte

Akhirnya saya selesai menulis solusi non-builtin saya dalam bahasa golf!

ḣ⁹’’¤;ṫḊ€Ç×⁸ị@⁹’¤¤ḷ/¤
çЀ⁸J‘¤µJ-*×NS
ÇḢḢ$Ṗ?

Terima kasih kepada HyperNeutrino karena telah menghemat satu byte!

Cobalah online! (kode spasi untuk kejelasan)

Cara yang sangat panjang untuk menghapus elemen ke-n dari daftar, akan ditingkatkan nanti


Jawaban ini dikalahkan oleh jawaban HyperNeutrino, Dennis dan Leaky Nun. Jelly sangat populer sebagai bahasa golf.

Penjelasan cepat:

ÇḢḢ$Ṗ?    Main link.
     ?    If
    Ṗ     after remove the last element, the value is not empty (truthy)
Ç         then execute the last link
 ḢḢ$      else get the element at index [1, 1].

çЀ⁸J‘¤µJ-*×NS     Helper link 1, take input as a matrix.
çЀ                Apply the previous link, thread right argument to
   ⁸J‘¤            the range [2, 3, ..., n+1]
       µ           With the result,
        J-*        generate the range [-1, 1, -1, 1, ...] with that length
           ×N      Multiply by negative
             S     Sum

ḣ⁹’’¤;ṫḊ€Ç×⁸ị@⁹’¤¤ḷ/¤    Helper link 2, take left input as a matrix, right input as a number in range [2..n+1]
ḣ
 ⁹’’¤                    Take head ρ-2 of the matrix
     ;                   concatenate with 
      ṫ                  tail ρ (that is, remove item ρ-1)
       Ḋ€                Remove first column
         Ç               Calculate determinant of remaining matrix
          ×         ¤    multiply by
                  ḷ/     the first column,
            ị@           row #
              ⁹’¤        ρ-1 (just removed in determinant calculation routine) of
           ⁸     ¤       the matrix.
pengguna202729
sumber
4

Jelly , 24 byte

œcL’$ṚÑ€
J-*×Ḣ€×ÇSµḢḢ$Ṗ?

Cobalah online!

Penjelasan

œcL’$ṚÑ€         Helper Link; get the next level of subdeterminants (for Laplace Expansion)
œc               Combinations without replacement of length:
  L’$            Length of input - 1 (this will get all submatrices, except it's reversed)
     Ṛ           Reverse the whole thing
      р         Get the determinant of each of these
J-*×Ḣ€×ÇSµḢḢ$Ṗ?  Main Link
              ?  If the next value is truthy
             Ṗ   Remove the last element (truthy if the matrix was at least size 2)
J-*×Ḣ€×ÇSµ       Then expand
          ḢḢ$    Otherwise, get the first element of the first element (m[0][0] in Python)
J                [1, 2, ..., len(z)]
 -*              (-1 ** z) for each z in the length range
   ×             Vectorizing multiply with
    Ḣ€           The first element of each (this gets the first column); modifies each row (makes it golfier yay)
      ×Ç         Vectorizing multiply with the subdeterminants
        S        Sum

-2 byte berkat solusi user202729

HyperNeutrino
sumber
4

MATL , 3 byte / 5 byte

Dengan fungsi bawaan

&0|

Cobalah online!

Tanpa built-in

Terima kasih kepada Misha Lavrov karena menunjukkan kesalahan, sekarang diperbaiki

YvpYo

Cobalah online!

Ini menghitung determinan sebagai produk dari nilai eigen, dibulatkan ke bilangan bulat terdekat untuk menghindari ketidakakuratan titik-mengambang.

Yv       % Implicit input. Push vector containing the eigenvalues
p        % Product
Yo       % Round. Implicit display
Luis Mendo
sumber
Bukankah produk dari nilai singular hanya memberi tahu Anda nilai absolut dari determinan?
Misha Lavrov
@MishaLavrov Anda benar sekali! Terima kasih telah memperhatikan. Saya memperbaikinya dengan menggunakan nilai eigen alih-alih nilai singular ... dan yang menyelamatkan 4 byte \ o /
Luis Mendo
4

R , 32 byte

function(m)Re(prod(eigen(m)$va))

Menggunakan Algoritma Not a Tree untuk mengambil nilai eigen dari matriks dan mengambil bagian nyata dari produk mereka.

Cobalah online!

JAD
sumber
Sangat elegan! +1.
Giuseppe
3

Oktaf , 30 byte

@(x)-prod(diag([~,l,~]=lu(x)))

Cobalah online!

atau, solusi 4 byte yang membosankan (disimpan 6 byte berkat Luis Mendo (lupa aturan tentang fungsi fungsi builtin)):

@det

Penjelasan:

Akan datang! :)

Stewie Griffin
sumber
3

TI-Basic, 2 byte

det(Ans

Ah, baiklah.

Tolong jangan mundur jawaban sepele.

Sebagai siswa sekolah menengah (yang terpaksa memiliki salah satu kalkulator ini), fungsi ini sangat berguna ...

benar-benar manusiawi
sumber
8
Ini masih berguna di perguruan tinggi - aljabar linier tidak hilang
Taylor Scott
5
@TaylorScott Bahkan, ia kembali dengan pembalasan dalam persamaan diferensial.
Mego
@Mego - Anda benar tentang itu; meskipun untuk beberapa alasan mereka membiarkan saya mengambil semua calc dan itu sebelum linear: /
Taylor Scott
1
@TaylorScott Karena pengawasan oleh departemen matematika universitas saya, linalg bukanlah prasyarat untuk diffeq ketika saya mengambilnya. Ketika profesor saya menyadari hal itu, dia dengan cepat memberi kami kursus kilat 3 hari di linalg.
Mego
3

Haskell, 62 byte

a#((b:c):r)=b*d(a++map tail r)-(a++[c])#r
_#_=0
d[]=1
d l=[]#l

Cobalah online! (Catatan kaki dengan kasus uji diambil dari solusi @ totallyhuman.)

dmenghitung penentu menggunakan ekspansi Laplace di sepanjang kolom pertama. Membutuhkan tiga byte lebih banyak daripada yang permanen .

Sievers Kristen
sumber
3

Python 2 , 95 byte

-12 byte terima kasih kepada Lynn.

Port jawaban Haskell saya .

f=lambda m:sum((-1)**i*v*f([j[:i]+j[i+1:]for j in m[1:]])for i,v in enumerate(m[0]))if m else 1

Cobalah online!

benar-benar manusiawi
sumber
1
Di sini, Anda juga dapat menggunakan []sebagai alas: f=lambda m:sum((-1)**i*v*f([j[:i]+j[i+1:]for j in m[1:]])for i,v in enumerate(m[0]))if m else 1untuk 95 byte!
Lynn
m==[]or sum(...)memberikan 92 byte.
Bubbler
3

Bahasa Wolfram (Mathematica) , 53 52 byte

1##&@@@(t=Tuples)@#.Signature/@t[Range@Tr[1^#]&/@#]&

Cobalah online!

Sayangnya, menghitung determinan matriks n demi n dengan cara ini menggunakan memori O ( n n ), yang menempatkan kotak uji besar di luar jangkauan.

Bagaimana itu bekerja

Bagian pertama 1##&@@@(t=Tuples)@#,, menghitung semua produk yang mungkin dari suatu istilah dari setiap baris dari matriks yang diberikan. t[Range@Tr[1^#]&/@#]memberikan daftar dengan panjang yang sama yang elemennya seperti {3,2,1}atau{2,2,3} mengatakan entri mana dari setiap baris yang kita pilih untuk produk yang sesuai.

Kami berlaku Signatureuntuk daftar kedua, yang memetakan permutasi bahkan 1, permutasi aneh -1, dan non-permutasi 0. Inilah tepatnya koefisien dengan mana produk yang sesuai muncul dalam determinan.

Akhirnya, kami mengambil produk titik dari dua daftar.


Jika bahkan Signatureterlalu banyak built-in, pada 73 byte kita dapat mengambil

1##&@@@(t=Tuples)@#.(1##&@@Order@@@#~Subsets~{2}&/@t[Range@Tr[1^#]&/@#])&

menggantinya dengan 1##&@@Order@@@#~Subsets~{2}&. Ini menghitung Signaturepermutasi-mungkin dengan mengambil produk yang Orderditerapkan pada semua pasangan elemen permutasi. Orderakan memberi 1jika pasangan dalam urutan naik, -1jika dalam urutan menurun, dan 0jika mereka sama.


-1 byte terima kasih kepada @ user202729

Misha Lavrov
sumber
1
52 byte (jika Anda tidak tahu tip golf Mathematica ini)
user202729
Memang, tapi entah bagaimana melupakannya di sini. Terima kasih!
Misha Lavrov
3

Python 3 , 238 byte , 227 byte , 224 byte , 216 byte

from functools import*
from itertools import*
r=range;n=len;s=sum
f=lambda l:s(reduce(lambda p,m:p*m,[l[a][b]for a,b in zip(r(n(l)),j)])*(-1)**s(s(y<j[x]for y in j[x:])for x in r(n(l)))for j in permutations(r(n(l))))

Cobalah online!

Solusi saya menggunakan definisi penentu untuk perhitungan. Sayangnya, kompleksitas dari algoritma ini n!dan saya tidak dapat menunjukkan bagian dari tes terakhir, tetapi secara teori ini mungkin.

Кирилл Малышев
sumber
3

CJam ( 50 45 bytes)

{:A_,{1$_,,.=1b\)/:CAff*A@zf{\f.*1fb}..-}/;C}

Ini adalah blok anonim (fungsi) yang mengambil array 2D pada stack dan meninggalkan integer pada stack.

Test suite online

Pembedahan

Ini mengimplementasikan algoritma Faddeev-LeVerrier , dan saya pikir ini adalah jawaban pertama untuk mengambil pendekatan itu.

Tujuannya adalah untuk menghitung koefisien ck dari polinomial karakteristik n×n matriks SEBUAH,

hal(λ)det(λsayan-SEBUAH)=k=0nckλk
dimana, jelas, cn=1 dan c0=(-1)ndetSEBUAH.

Koefisien ditentukan secara rekursif dari atas ke bawah, berdasarkan matriks bantu M.,

M00cn=1(k=0)MkAMk1+cnk+1Icnk=1ktr(AMk)k=1,,n .

The code never works directly with cnk and Mk, but always with (1)kcnk and (1)k+1AMk, so the recurrence is

(1)kcnk=1ktr((1)k+1AMk)(1)k+2AMk+1=(1)kcnkAA((1)k+1AMk)

{               e# Define a block
  :A            e#   Store the input matrix in A
  _,            e#   Take the length of a copy
  {             e#     for i = 0 to n-1
                e#       Stack: (-1)^{i+2}AM_{i+1} i
    1$_,,.=1b   e#       Calculate tr((-1)^{i+2}AM_{i+1})
    \)/:C       e#       Divide by (i+1) and store in C
    Aff*        e#       Multiply by A
    A@          e#       Push a copy of A, bring (-1)^{i+2}AM_{i+1} to the top
    zf{\f.*1fb} e#       Matrix multiplication
    ..-         e#       Matrix subtraction
  }/
  ;             e#   Pop (-1)^{n+2}AM_{n+1} (which incidentally is 0)
  C             e#   Fetch the last stored value of C
}
Peter Taylor
sumber
2

Python 2, 75 bytes

f=lambda m,p=[]:m[0][0]*f(zip(*p+m[1:])[1:])-f(m[1:],p+m[:1])if m else[]==p

Try it online!

xnor
sumber
2

SageMath, various

Here are a bunch of methods for computing the determinant that I found interesting, all programmed in SageMath. They can all be tried here.

Builtin, 3 bytes

det

This one isn't too interesting. Sage provides global-level aliases to many common operations that would normally be object methods, so this is shorter than lambda m:m.det().


Real Part of Product of Eigenvalues, 36 bytes

lambda m:real(prod(m.eigenvalues()))

Unfortunately, eigenvalues is not one of those global-level aliases. That, combined with the fact that Sage doesn't have a neat way to compose functions, means we're stuck with a costly lambda. This function symbolic values which are automatically converted to numeric values when printed, so some floating point inaccuracy may be present in some outputs.


Product of Diagonal in Jordan Normal Form, 60 bytes

lambda m:prod(m.jordan_form()[x,x]for x in range(m.nrows()))

In Jordan Normal form, an NxN matrix is represented as a block matrix, with N blocks on the diagonal. Each block consists of either a single eigenvalue, or a MxM matrix with a repeated eigenvalue on the diagonal and 1s on the super-diagonal (the diagonal above and to the right of the "main" diagonal). This results in a matrix with all eigenvalues (with multiplicity) on the main diagonal, and some 1s on the super-diagonal corresponding to repeated eigenvalues. This returns the product of the diagonal of the Jordan normal form, which is the product of the eigenvalues (with multiplicty), so this is a more roundabout way of performing the same computation as the previous solution.

Because Sage wants the Jordan normal form to be over the same ring as the original matrix, this only works if all of the eigenvalues are rational. Complex eigenvalues result in an error (unless the original matrix is over the ring CDF (complex double floats) or SR). However, this means that taking the real part is not necessary, compared to the above solution.


Product of Diagonal in Smith Decomposition

lambda m:prod(m.smith_form()[0].diagonal())

Unlike Jordan normal form, Smith normal form is guaranteed to be over the same field as the original matrix. Rather than computing the eigenvalues and representing them with a block diagonal matrix, Smith decomposition computes the elementary divisors of the matrix (which is a topic a bit too complicated for this post), puts them into a diagonal matrix D, and computes two matrices with unit determinant U and V such that D = U*A*V (where A is the original matrix). Since the determinant of the product of matrices equals the product of the determinants of the matrices (det(A*B*...) = det(A)*det(B)*...), and U and V are defined to have unit determinants, det(D) = det(A). The determinant of a diagonal matrix is simply the product of the elements on the diagonal.

Laplace Expansion, 109 bytes

lambda m:m.nrows()>1and sum((-1)**j*m[0,j]*L(m[1:,:j].augment(m[1:,j+1:]))for j in range(m.ncols()))or m[0,0]

This performs Laplace expansion along the first row, using a recursive approach. det([[a]]) = a is used for the base case. It should be shorter to use det([[]]) = 1 for the base case, but my attempt at that implementation had a bug that I haven't been able to track down yet.


Leibniz's Formula, 100 bytes

L2 = lambda m:sum(sgn(p)*prod(m[k,p[k]-1]for k in range(m.ncols()))for p in Permutations(m.ncols()))

This directly implements Leibniz's formula. For a much better explanation of the formula and why it works than I could possibly write, see this excellent answer.


Real Part of e^(Tr(ln(M))), 48 bytes

lambda m:real(exp(sum(map(ln,m.eigenvalues()))))

This function returns symbolic expressions. To get a numerical approximation, call n(result) before printing.

This is an approach that I haven't seen anyone use yet. I'm going to give a longer, more-detailed explanation for this one.

Let A be a square matrix over the reals. By definition, the determinant of A is equal to the product of the eigenvalues of A. The trace of A is equal to the sum of A's eigenvalues. For real numbers r_1 and r_2, exp(r_1) * exp(r_2) = exp(r_1 + r_2). Since the matrix exponential function is defined to be analogous to the scalar exponential function (especially in the previous identity), and the matrix exponential can be computed by diagonalizing the matrix and applying the scalar exponential function to the eigenvalues on the diagonal, we can say det(exp(A)) = exp(trace(A)) (the product of exp(λ) for each eigenvalue λ of A equals the sum of the eigenvalues of exp(A)). Thus, if we can find a matrix L such that exp(L) = A, we can compute det(A) = exp(trace(L)).

We can find such a matrix L by computing log(A). The matrix logarithm can be computed in the same way as the matrix exponential: form a square diagonal matrix by applying the scalar logarithm function to each eigenvalue of A (this is why we restriced A to the reals). Since we only care about the trace of L, we can skip the construction and just directly sum the exponentials of the eigenvalues. The eigenvalues can be complex, even if the matrix isn't over the complex ring, so we take the real part of the sum.

Mego
sumber
1
The last part is a fascinating idea, but the header and explanation don't match the code, which doesn't take a matrix logarithm. It's just real(prod(m.eigenvalues())) ungolfed.
Peter Taylor
2

Java 8, 266 261 259 258 bytes

long d(int[][]m){long r=0;int i=0,j,k,l=m.length,t[][]=new int[l-1][l-1],q=m[0][0];if(l<3)return l<2?q:q*m[1][1]-m[0][1]*m[1][0];for(;i<l;r+=m[0][i]*(1-i++%2*2)*d(t))for(j=0;++j<l;)for(k=l;k-->0;){q=m[j][k];if(k<i)t[j-1][k]=q;if(k>i)t[j-1][k-1]=q;}return r;}

Look mom, no build-ins.. because Java has none.. >.>

-7 bytes thanks to @ceilingcat.

Explanation:

Try it here. (Only the last test case is too big to fit in a long of size 263-1.)

long d(int[][]m){             // Method with integer-matrix parameter and long return-type
  long r=0;                   //  Return-long, starting at 0
  int i=0,j,k,                //  Index-integers
      l=m.length,             //  Dimensions of the square matrix
      t[][]=new int[l-1][l-1],//  Temp-matrix, one size smaller than `m`
      q=m[0][0];              //  The first value in the matrix (to reduce bytes)
  if(l<3)                     //  If the dimensions are 1 or 2:
    return l<2?               //   If the dimensions are 1:
      q                       //    Simply return the only item in it
     :                        //   Else (the dimensions are 2):
      q*m[1][1]-m[0][1]*m[1][0];
                              //    Calculate the determinant of the 2x2 matrix
                              //  If the dimensions are 3 or larger: 
  for(;i<l;                   //  Loop (1) from 0 to `l` (exclusive)
      r+=                     //    After every iteration: add the following to the result:
         m[0][i]              //     The item in the first row and `i`'th column,
         *(1-i++%2*2)         //     multiplied by 1 if `i` is even; -1 if odd,
         *d(t))               //     multiplied by a recursive call with the temp-matrix
    for(j=0;                  //   Reset index `j` to 0
        ++j<l;)               //   Inner loop (2) from 0 to `l` (exclusive)
      for(k=l;k-->0;){        //    Inner loop (3) from `l-1` to 0 (inclusive)
        q=m[j][k];            //     Set the integer at location `j,k` to reduce bytes
        if(k<i)               //     If `k` is smaller than `i`:
          t[j-1][k]=q;        //      Set this integer at location `j-1,k`
        if(k>i)               //     Else-if `k` is larger than `i`:
          t[j-1][k-1]=q;      //      Set this integer at location `j-1,k-1`
                              //     Else: `k` and `i` are equals: do nothing (implicit)
      }                       //    End of inner loop (3)
                              //   End of inner loop (2) (implicit / single-line body)
                              //  End of loop (1) (implicit / single-line body)
  return r;                   //  Return the result-long
}                             // End of method
Kevin Cruijssen
sumber
2

JavaScript (ES6), 91

Recursive Laplace

q=(a,s=1)=>+a||a.reduce((v,[r],i)=>v-(s=-s)*r*q(a.map(r=>r.slice(1)).filter((r,j)=>j-i)),0)

Less golfed

q = (a,s=1) => // s used as a local variable
  a[1] // check if a is a single element array 
       // if array, recursive call expanding along 1st column
  ? a.reduce((v,[r],i) => v-(s=-s)*r*q(a.map(r=>r.slice(1)).filter((r,j)=>j-i)),0) 
  : +a // single element, convert to number

Test

q=(a,s=1)=>+a||a.reduce((v,[r],i)=>v-(s=-s)*r*q(a.map(r=>r.slice(1)).filter((r,j)=>j-i)),0)

TestCases=`[[42]] -> 42
[[2, 3], [1, 4]] -> 5
[[1, 2, 3], [4, 5, 6], [7, 8, 9]] -> 0
[[13, 17, 24], [19, 1, 3], [-5, 4, 0]] -> 1533
[[372, -152, 244], [-97, -191, 185], [-53, -397, -126]] -> 46548380
[[100, -200, 58, 4], [1, -90, -55, -165], [-67, -83, 239, 182], [238, -283, 384, 392]] -> 571026450
[[432, 45, 330, 284, 276], [-492, 497, 133, -289, -28], [-443, -400, 56, 150, -316], [-344, 316, 92, 205, 104], [277, 307, -464, 244, -422]] -> -51446016699154`
.split('\n')

TestCases.forEach(r=>{
  [a,k] = r.split (' -> ')
  a = eval(a)
  d = q(a)
  console.log('Test '+(k==d ? 'OK':'KO')+
    '\nMatrix '+a.join('|')+
    '\nResult '+d+
    '\nCheck  '+k)
})

edc65
sumber
83 bytes with the same behavior
Arnauld
Or 85 bytes to support the empty matrix (whose determinant should be 1).
Arnauld
(I used the same optimizations in this answer, which is derived from yours.)
Arnauld
1

Java (OpenJDK 8), 195 192 177 bytes

long d(int[][]m){long D=0;for(int l=m.length-1,t[][]=new int[l][l],i=0,j,k;i<=l;D+=m[0][i]*(1-i++%2*2)*(l<1?1:d(t)))for(j=0;j<l*l;)t[j/l][k=j%l]=m[1+j++/l][k<i?k:k+1];return D;}

Try it online!

Like many other answers, this also uses the Laplace formula. A slightly less golfed version:

long d(int[][]m){
  long D=0;
  int l=m.length-1,t[][]=new int[l][l],i=0,j,k;
  for(;i<=l;)
    for(j=0;j<l*l;)
      t[j/l][k=j%l]=m[1+j++/l][k<i?k:k+1];
    D+=m[0][i]*(1-i++%2*2)*(l<1?1:d(t));
  return D;
}
ceilingcat
sumber