Bir Tamsayı Matrisinin Belirleyicisi


34

Giriş olarak kare tamsayılı bir matris verildiğinde, matrisin determinantını çıktılar.

kurallar

  • Matristeki tüm öğelerin, matrisin belirleyicisinin ve matristeki toplam öğe sayısının, diliniz için temsil edilebilir tam sayı aralığında olduğunu varsayabilirsiniz.
  • 0'ın kesirli bir kısmı ile bir ondalık / değişken değerin çıkmasına izin verilir (örneğin 42.0yerine 42).
  • Yerleşiklere izin verilir, ancak yerleşikleri kullanmayan bir çözüm eklemeniz önerilir.

Test Kılıfları

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


Desteklenmesi gereken maksimum boyutta matris var mı yoksa keyfi mi?
Taylor Scott

1
@TaylorScott İlk kural listelenen: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
Birbirini ard arda 4 Jelly cevapları olduğunda ilginç bir zorluk olduğunu biliyorsun ...
tamamen insan

Yanıtlar:


25

Jöle , 15 bayt

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

Çevrimiçi deneyin!

Nasıl çalışır

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

Neden çalışıyor - matematik versiyonu

Operatör det bir matris alır ve bir skalar döndürür. Bir n -by- n matris topluluğu olarak düşünülebilir n uzunluğunun vektörler n böylece det götüren bir işlev gerçekten n ℤ gelen vektörler n bir skaler ve getiri.

Bu nedenle, geç det ( v 1 , v 2 , v 3 , ..., v , n için) det [ h 1 h 2 hac 3 ... v n ].

Uyarı bu det her bir bağımsız değişken olarak lineerdir, yani det ( v 1 + λ w 1 , v 2 , v 3 , ..., v , n ) = det ( v 1 , hac 2 , hac 3 , ..., v , n ) + λ det ( w , 1 , v 2 , v 3 , ..., v , n ). Bu nedenle, (ℤ n ) n'den doğrusal bir haritadır. ℤ için.

Doğrusal haritanın altındaki temel imajını belirlemek yeterlidir. (ℤ temeli n ) n oluşur , n ℤ temeli elemanlarının kat tensör ürün , n , ieeg E 5 ⊗ E 3 ⊗ e 1 ⊗ E 5 ⊗ e 1 . Aynı tensörleri içeren tensör ürünleri sıfıra gönderilmelidir, çünkü iki sütunun aynı olduğu bir matrisin determinantı sıfırdır. Farklı temel elementlerin tensör ürünlerinin ne gönderildiğini kontrol etmeye devam eder. Tensör ürünündeki vektörlerin indeksleri bir çekişme, yani permütasyonların bile 1'e gönderildiği ve tek permütasyonların -1'e gönderildiği bir permütasyon oluşturur.

Örneğin, [[1, 2], [3, 4]] determinantını bulmak için: sütunların [1, 3] ve [2, 4] olduğuna dikkat edin. [1, 3] 'ü (1 e 1 + 3 e 2 ) ve (2 e 1 + 4 e 2 ) vermek üzere ayrıştırıyoruz . Tensör ürünündeki ilgili eleman (1 e 1 ⊗ 2 e 1 + 1 e 1 ⊗ 4 e 2 + 3 e 2 ⊗ 2 e 1 + 3 e 2 ⊗ 4 e 2 ) (2 e 1 1 e 1 + 4 e 1 2 e 2 + 6 e 2 1 e 1 + 12 e 2 ⊗ e 2). Bu nedenle:

det [[1, 2], [3, 4]]
= det (1 e 1 + 3 e 2 , 2 e 1 + 4 e 2 )
= det (2 e 1 1 e 1 + 4 e 1 2 e 2 + 6 e 2 1 e 1 + 12 e 2 ⊗ e 2 )
= det (2 e 1 1 e 1 ) + det (4 e 1 2 e 2 ) + det (6 e 2 1 e 1 ) + det (12 e2 ⊗ e 2 )
= 2 det (e 1 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

Şimdi, permütasyonun paritesini bulmak için kullanılan formülün geçerli olduğunu kanıtlamaya devam etmektedir. Kodumun yaptığı şey aslında ters çevrimlerin sayısını bulmak, yani soldaki bir öğenin sağdaki bir öğeden daha büyük olduğu yerler (zorunlu olarak arka arkaya değil).

Örneğin, 3614572 numaralı permütasyonda 9 ters çevrme (31, 32, 61, 64, 65, 62, 42, 52, 72) vardır, bu yüzden permütasyon tuhaftır.

Gerekçe, her bir aktarımın (iki elemanın yer değiştirmesi) ya bir inversiyon eklemesi ya da bir inversiyonu alması, inversiyon sayısının paritesini değiştirmesi ve permütasyonun paritesinin, permütasyona ulaşmak için gereken transpozisyon sayısının paritesi olmasıdır.

Bu nedenle, sonuç olarak, formülümüz aşağıdaki gibidir:

Neden çalışıyor - mathy olmayan versiyon

σ 𝕊 bir permütasyon burada n, tüm permütasyon grubu , n harf ve SGN AKA permütasyon işareti, (-1) permütasyon parite yükseltilir ve bir ij (olup ij ) inci hanesi matris ( i aşağı, j karşısında).


17
Bu "matematiksiz olmayan versiyon" oldukça lanet olası bir matematik.
MD XF

6
@ MDXF formülleri ve semboller ve sayılar zor matematik oluşturur. Matematik, soyutlama, genelleme ve sembollerin biçimsel manipülasyonlarının ardındaki mantıktır.
Leaky Nun

7
@ JAB Jelly kendi özel kod sayfasını uygular . (Günlerden birinde, TIO kod sayfasına bir link verecek ...)
tamamen insanlık

1
@Mego "köşegen ürünler toplamı" yalnızca 1x1, 2x2 ve 3x3 matrislerinde çalışır. Daha büyük matrisler için tüm permütasyonları ve eşliklerini dikkate almanız gerekir.
Sızdıran Rahibe

3
Aslında +1 aslında "bu formül abcxyz sayfasında listelendiği için doğru olmalı" demek yerine ismin ispatı içeriyor.
user202729

11

R , 3 bayt

Önemsiz Çözüm

det

Çevrimiçi deneyin!

R , 94 92 bayt

yeniden uygulanmış çözüm

Jarko Dubbeldam tarafından aşıldı

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

Çevrimiçi deneyin!

Tekrarlı olarak matrisin ilk sütununa kadar küçükler tarafından genişleme kullanır.

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



9

Jöle , 16 15 12 10 bayt

Ḣ×Zß-Ƥ$Ṛḅ-

Laplace genişlemesini kullanır . 3 5 baytlık golf için teşekkürler !

Çevrimiçi deneyin!

Nasıl çalışır

Ḣ×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.

8

Wolfram Dili (Mathematica) , 14 ile 42 bayt arasında

Yerleşikleri tamamen önleyen 3 baytlık bir yerleşik ve 53 baytlık bir çözüme sahip olduk , işte bunlar arasında bir yerde tuhaf çözümler var.

Wolfram Dil sahip bir çok daha basit bir yapıya sahip diğer matrislerin ürünlerine matrisleri çürüyen için çok yoğun fonksiyonlar. En basitlerinden biri (daha önce duyduğum anlamına gelir) Ürdün'ün ayrışmasıdır. Her matris, bu matrisin Jordan ayrışması olarak adlandırılan belirli bir yapıya sahip, diyagonal bloklardan yapılmış üst üçgen matrisine benzer (muhtemelen karmaşık değerli). Benzerlik determinantları korur ve üçgen matrisin determinantı, diyagonal elemanların ürünüdür, bu nedenle determinantı aşağıdaki 42 bayt ile hesaplayabiliriz :

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

Belirleyici, aynı zamanda, bir matrisin özdeğerlerinin çarpımına eşittir. Neyse ki, Wolfram'ın özdeğer işlevi çokluğun kaydını tutar (köşegenleştirilemeyen matrisler için bile), bu nedenle aşağıdaki 20 baytlık çözümü elde ediyoruz :

1##&@@Eigenvalues@#&

Bir sonraki çözüm biraz hile yapmak ve neden işe yaradığından emin değilim. Bir n fonksiyon listesinin Wronskian'ı, fonksiyonların ilk n- 1 türevlerinin matrisinin belirleyicisidir . Wronskianİşleve bir tamsayı matrisi verir ve farklılaşma değişkeninin 1 olduğunu söylersek, bir şekilde matrisin determinantını yayar. Garip, ama " Det" harflerini içermiyor ve sadece 14 bayt ...

#~Wronskian~1&

(Casoratian belirleyici 1 daha byte için, hem de çalışır: #~Casoratian~1&)

Soyut cebir alanında, bir belirleyicisi n  x  n ise matris (harita olarak k → k yani çarpma belirleyici tarafından düşüncesi) n matris inci dış güç (bir izomorfizm çekme sonra k → ⋀ n k n ) Wolfram dilinde, bunu aşağıdaki 26 bayt ile yapabiliriz :

HodgeDual[TensorWedge@@#]&

Ve işte sadece pozitif belirleyiciler için çalışan bir çözüm. Bir n -boyutlu birim hiper küpü alıp ona doğrusal bir dönüşüm uygularsak , sonuçta elde edilen bölgenin n -boyutlu "hacmi", dönüşümün determinantının mutlak değeridir. Bir küpe doğrusal bir dönüşüm uygulamak, paralel bir bölmeyi verir ve hacmini aşağıdaki 39 bayt kod ile alabiliriz:

RegionMeasure@Parallelepiped[Last@#,#]&

1
Bu çizgiler boyunca sahip olduğum çözüm Exp@*Tr@*MatrixLog, maalesef bu, tekil matrislerde işe yaramaz.
Misha Lavrov

1
@MishaLavrov Ooh, bu zekice! Bence düzeltebilirsin Check[E^Tr@MatrixLog@#,0]&.
Ağaç değil

Bu harika! Daha Checkönce farkında değildim .
Misha Lavrov

1
Jordan Ayrışması için bir meydan okuma yarattımBir süre önce . Sen de onunla ilgilenebilirsin. Ne güzel bir cevap!
Mego

8

Haskell , 71 bayt

Lynn sayesinde -3 bayt. Bir diğeri Craig Roy sayesinde tozu byte ediyor.

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

Çevrimiçi deneyin! Optimizasyon amacıyla bayrak eklendi -O. Bu gerekli değil.

Açıklama (eski)

f kofaktör genişlemesini tekrar tekrar uygular.

f[[x]]=x

Bu çizgi, bir 1 × 1 matrisin bu durumda determinanttır mat[0, 0].

f(h:t)=

Bu Haskell kullanır , matrisi bir kafaya (ilk satır) ve bir kuyruğu (matrisin geri kalanına ) kırmak için desen eşleştirmesini .

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

Matrisin başını numaralandırın (sayının tam listesini ve başını kaydırarak) ve üzerine tekrarlayın.

           (-1)*i*v

Belirleyicinin hesaplanmasında dönüşümlü toplama ve çıkarma işlemlerinden oluştuğu için endeksinin endeks olup olmamasına göre sonucu olumsuzlayın.

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

Bu, esasen kuyruğun it sütununu alarak kaldırır. i elemanları ve birinci ile satır ile birleştirerek th (i + 1) elemanları kuyruk her satır için düştü.

                   *f

Yukarıdaki sonucun determinantını hesaplayın ve sonucu ile çarpın (-1)*i*v.

       sum

Yukarıdaki listenin sonucunu toplayın ve geri gönderin.


2
sum[(-1)^i*...ile değiştirirseniz 1 byte tasarruf edebilirsinizfoldr(-)0[...
Craig Roy

6

Proton , 99 bayt

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)

Çevrimiçi deneyin!

Bay Xcoder sayesinde -3 bayt
Xcoder sayesinde -3 bayt Baygın Erik sayesinde -3 bayt

İlk satıra yayılma


Sadece Proton'un determinant için yerleşik olmadığı için.
user202729

103 Bayt . ((~i%2)*2-1)->((-i%2)|1)
Bay Xcoder

Ayrıca veya j!=iile değiştirerek 102 bayt . j-ii-j
Bay Xcoder


@EriktheOutgolfer Ah evet, teşekkürler!
HyperNeutrino,

5

Octave , 28 bayt

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

Çevrimiçi deneyin!

Bu , bir matris X'in bir ortogonal matris Q ve bir üst üçgen matris R'ye ayrıştırılmasını kullanır . X'in determinantı, Q ve R'nin ürünüdür . Ortogonal bir matris birim determinanta sahiptir ve üçgen matris için determinant, çapraz girişlerinin ürünüdür. Tek bir çıkışla çağırılan Octave fonksiyonunu verirqr R .

Sonuç en yakın tam sayıya yuvarlanır. Büyük girdi matrisleri için kayan nokta yanlışlıkları aşmada hata 0.5üretebilir ve bu nedenle yanlış sonuç üretebilir.


1
Yerleşimden detkaçmanın ilginç bir yolu . ;)
17'de

1
@tomsmeding :-) Ayrıca zaten Stewie'nin cevabında
Luis Mendo


5

C,  176  125 bayt

42 byte golf oynadığı için @ceilingcat'e ve her bir byte'ı kaydettiği için hem @ Lynn hem de @Jonathan Frech'e teşekkürler!

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;}

İlk satır boyunca Laplace genişlemesini kullanarak determinantı hesaplar .

Çevrimiçi deneyin!

unrolled:

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;
}

(i%2*-2+1)(1-i%2*2)bir bayt daha kaydeder.
Lynn

n+1+colabilir n-~c.
Jonathan Frech

Öner i=syerinereturn s
ceilingcat

5

Jöle , 43 bayt

Sonunda yerleşik olmayan çözümümü bir golf dilinde yazdım!

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

Bir bayt tasarrufu için HyperNeutrino teşekkürler !

Çevrimiçi deneyin! (netlik için aralıklı kod)

n'th elementleri listeden çıkarmanın çok uzun bir yolu, daha sonra gelişecek


Bu cevap HyperNeutrino, Dennis ve Leaky Nun'un cevaplarıyla aşılmıştı. Jöle çok bir golf dili olarak popüler.

Hızlı açıklama:

ÇḢḢ$Ṗ?    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.

4

Jöle , 24 bayt

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

Çevrimiçi deneyin!

açıklama

œ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

User202729 çözümü sayesinde -2 byte


4

Matl , 3 bayt / 5 bayt

Yerleşik işleviyle

&0|

Çevrimiçi deneyin!

Yerleşik olmadan

Misha Lavrov'a bir hatayı işaret ettiği için teşekkürler , şimdi düzeltildi

YvpYo

Çevrimiçi deneyin!

Bu, determinantı kayan nokta yanlışlıklarından kaçınmak için en yakın tam sayıya yuvarlanan özdeğerlerin ürünü olarak hesaplar.

Yv       % Implicit input. Push vector containing the eigenvalues
p        % Product
Yo       % Round. Implicit display

Tekil değerlerin ürünü sadece size determinantın mutlak değerini söylemez mi?
Misha Lavrov

@MishaLavrov Tamamen haklısın! Fark ettiğin için teşekkürler. Tekil değerler yerine özdeğerler kullanarak düzelttim ... ve 4 byte kurtardı.
Luis Mendo

4

R , 32 bayt

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

Bir Ağacın, matrisin özdeğerlerini alma ve ürününün gerçek kısmını alma algoritmasını kullanır.

Çevrimiçi deneyin!


Çok zarif! +1.
Giuseppe

3

Oktav , 30 bayt

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

Çevrimiçi deneyin!

veya, sıkıcı 4 baytlık çözüm (Luis Mendo sayesinde 6 bayt kurtarıldı (yerleşik işlevlerle ilgili kuralları unuttum):

@det

Açıklama:

Geliyor! :)


3

TI-Basic, 2 bayt

det(Ans

Ah, peki.

Lütfen önemsiz cevapları unutma.

Bir lise öğrencisi olarak (bu hesaplayıcılardan birine sahip olmak zorunda olan), bu fonksiyon hella faydalıdır, yani ...


8
Üniversitede hala yararlı bir hella var - Doğrusal cebir geçmiyor
Taylor Scott

5
@TaylorScott Aslında, diferansiyel denklemlerde bir intikam ile geri geliyor.
Mego

@Mego - Bu konuda haklısın; bir nedenden ötürü, tüm calc ve her şeyden önce onu almama izin verdiler: /
Taylor Scott

1
@TaylorScott Üniversitemin matematik bölümünün gözetimi nedeniyle, linalg aldığımda fark için ön şart değildi. Profesörüm bunu fark ettiğinde, hızlı bir şekilde bize linalg'de 3 günlük bir çarpışma kursu verdi.
Mego

3

Haskell, 62 bayt

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

Çevrimiçi deneyin! (@ Totallyhuman'ın çözümünden alınan test davaları ile altbilgi.)

dİlk sütun boyunca bir Laplace genişlemesi kullanarak determinantı hesaplar. Üçten fazla bayt İhtiyaçları kalıcı .



3

Wolfram Dili (Mathematica) , 53 52 bayt

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

Çevrimiçi deneyin!

Ne yazık ki, determinantı işlem n ile n (bu şekilde kullanımları O matris n , n ulaşamayacağı bir) bellek, koyar geniş test durumları.

Nasıl çalışır

İlk bölüm, 1##&@@@(t=Tuples)@#bir terimin olası tüm ürünlerini verilen matrisin her satırından hesaplar. t[Range@Tr[1^#]&/@#]elemanları gibi şeyler olan {3,2,1}veya {2,2,3}aynı ürün için hangi sırayı seçtiğimizi söyleyen aynı uzunlukta bir liste verir .

Bu Signaturepermütasyonları hatta 1tuhaf permütasyonları -1ve non-permütasyonlarını bile haritalayan ikinci listeye uygulanır 0. Bu, tam olarak ilgili ürünün determinantta göründüğü katsayısıdır.

Son olarak, iki listenin nokta ürününü alıyoruz.


SignatureÇok fazla dahili bile olsa , 73 baytta alabiliriz.

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

ile değiştirerek 1##&@@Order@@@#~Subsets~{2}&. Bu Signature, permütasyonun Ordertüm element çiftlerine uygulanan ürünü alarak muhtemel permütasyonu hesaplar . Orderverecek 1çifti, küçükten büyüğe ise -1o büyükten küçüğe, ve eğer 0eşitse.


@ User202729 sayesinde -1 bayt


1
52 bytes (bu Mathematica golf bahşişini bilmiyorsanız bile)
user202729

Yaptım, ama bir şekilde burada unutmuşum. Teşekkürler!
Misha Lavrov

3

Python 3 , 238 bayt , 227 bayt , 224 bayt , 216 bayt

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

Çevrimiçi deneyin!

Benim çözümüm hesaplamalar için determinant tanımını kullanıyor. Ne yazık ki, bu algoritmanın karmaşıklığı n!ve son testin geçişini gösteremiyorum, ancak teoride bu mümkün.


3

CJam ( 50 45 bayt)

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

Bu, yığın üzerinde 2B bir dizi alan ve yığında bir tamsayı bırakan anonim bir bloktur (fonksiyon).

Çevrimiçi test paketi

teşrih

Bu Faddeev-LeVerrier algoritmasını uygular ve bence bu yaklaşımı benimseyen ilk cevap bu.

Amaç katsayıları hesaplamaktır ck karakteristik polinomun nxn matris bir,

p(λ)det(λbenn-bir)=Σk=0nckλk
nerede, açıkça cn=1 ve c0=(-1)ndetbir.

Katsayılar, yardımcı matrislerin tonu ile yukarıdan aşağıya doğru özyinelemeli olarak belirlenir 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
}



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.


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

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


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;
}

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.