整数行列の決定要因


34

入力として正方整数行列を指定し、行列の行列式を出力します。

ルール

  • マトリックス内のすべての要素、マトリックスの行列式、およびマトリックス内の要素の総数は、言語の表現可能な整数の範囲内にあると想定できます。
  • 0の小数部を持つ10進数/浮動小数点値の出力が許可されます(例:の42.0代わりに42)。
  • ビルトインは許可されますが、ビルトインを使用しないソリューションを含めることをお勧めします。

テストケース

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


サポートする必要があるマトリックスの最大サイズはありますか、それとも任意ですか?
テイラースコット

1
@TaylorScott最初にリストされているルール: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
あなたは4を持っているゼリーは...アウトゴルフ互いに連続して応答したときに、あなたが興味深い課題を持って知っている
totallyhuman

回答:


25

ゼリー、15 バイト

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

オンラインでお試しください!

使い方

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

なぜ機能するか-マシー版

演算子detは行列を取り、スカラーを返します。N行列n個の行列は、の集まりと考えることができ、N長さのベクトルNので、DETをとる関数本当にN ℤからベクトルnはスカラーと戻ります。

したがって、det [ v 1 v 2 v 3 ... v n ] に対してdetv 1v 2v 3、...、v n)を記述します。

ことを通知DETは、各引数で、即ち直線的であるDETV 1W 1V 2V 3、...、V N)= DETV 1V 2V 3、...、VはN)+ λdetw 1v 2v 3、...、v n)。したがって、(ℤするから線形マップであるNN ℤへ。

線形マップの下で基底の画像を決定すれば十分です。(ℤ用の基礎NNから成るN倍テンソルℤの基本要素の生成物N、ieeg E 5 ⊗E 3 ⊗E 1 ⊗E 5 ⊗E 1。2つの列が同一である行列の行列式はゼロであるため、同一のテンソルを含むテンソル積はゼロに送信する必要があります。異なる基底要素のテンソル積が何に送られるかを確認することは残っています。テンソル積のベクトルのインデックスは全単射、つまり順列を形成します。偶数順列は1に送信され、奇数順列は-1に送信されます。

たとえば、[[1、2]、[3、4]]の行列式を見つけるには、列が[1、3]および[2、4]であることに注意してください。[1、3]を分解して(1 e 1 + 3 e 2)と(2 e 1 + 4 e 2)を求めます。テンソル積に対応する要素は、(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 ⊗E 1つの + 4 E 1 ⊗E 2 + 6 E 2 ⊗E 1 + 12 E 2 ⊗E 2)。したがって:

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 E2 ⊗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

現在、順列のパリティを見つけるための式が有効であることを証明するために残っています。私のコードが行うことは、基本的に反転の数、つまり、左側の要素が右側の要素よりも大きい(必ずしも連続的ではない)場所を見つけることです。

たとえば、順列3614572では、9回の反転(31、32、61、64、65、62、42、52、72)があるため、順列は奇数です。

正当化は、各転置(2つの要素のスワップ)が1つの反転を追加するか、1つの反転を取り除いて、反転の数のパリティを交換することであり、順列のパリティは、順列を達成するために必要な転置の数のパリティです。

したがって、結論として、式は次のようになります。

なぜ機能するか-非数学バージョン

σは𝕊の順列である場合、N上のすべての順列の群N文字、及びSGNは順列の符号で、AKA(-1)順列のパリティに上げ、そしてijは(あるIJ番目のエントリマトリックス(iが下、jが横)。


17
その「非数学バージョン」は非常にマチです。
MD XF

6
@MDXFの数式と記号および数値は、数学を構成することはほとんどありません。数学は、記号の形式的な操作の背後にある抽象化と一般化、およびロジックです。
リーキー修道女

7
@JAB Jellyは独自のカスタムコードページを実装します。(これらの日のうちの1つ、TIOはコードページへのリンクを含みます...)
totallyhuman

1
@Megoの「対角積の合計」は、1x1、2x2、および3x3行列でのみ機能します。より大きな行列の場合、すべての順列とそのパリティを考慮する必要があります。
リーキー修道女

3
以下のための1 、実際には、代わりに「それは本当でなければならないABCXYZこの式は、ページに記載されているので」と言ってのポストに証拠が含まれています。
-user202729

11

R、3バイト

簡単な解決策

det

オンラインでお試しください!

R94 92バイト

再実装されたソリューション

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)

オンラインでお試しください!

マトリックスの最初の列で未成年者による展開を再帰的に使用します。

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

ゼリー16 15 12 10バイト

Ḣ×Zß-Ƥ$Ṛḅ-

ラプラス展開を使用します。3 5バイトのゴルフをしてくれた@milesに感謝します!

オンラインでお試しください!

使い方

Ḣ×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言語(Mathematica)、14〜42バイト

私たちは持っていた内蔵の3バイト53バイトのソリューションので、ここでは、完全にビルトインを回避し、いくつかの奇妙な解決策はどこかの間です。

Wolfram言語には行列をより単純な構造を持つ他の行列の積に分解するため非常に強力な関数がたくさんあります。より単純なものの1つ(以前に聞いたことがあることを意味します)は、ジョーダン分解です。すべての行列は、その行列のジョーダン分解と呼ばれる特定の構造を持つ対角ブロックで構成される(おそらく複素値の)上三角行列に似ています。類似性は行列式を保持し、三角行列の行列式は対角要素の積であるため、次の42バイトで行列式を計算できます

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

また、行列式は、行列の固有値の積に等しく、多重度があります。幸いなことに、Wolframの固有値関数は、多重度を追跡します(非対角化可能行列の場合でも)。したがって、次の20バイトのソリューションが得られます。

1##&@@Eigenvalues@#&

次の解決策は一種の不正行為であり、なぜそれが機能するのか本当にわかりません。n個の関数のリストのWronskianは、関数の最初のn -1導関数の行列の行列式です。Wronskian関数に整数の行列を与え、微分の変数が1であると言うと、どういうわけか行列の行列式を吐き出します。奇妙ですが、「Det」という文字は含まれておらず、14バイトしかありません…

#~Wronskian~1&

(Casoratian決定は、1以上のバイトのために、同様に動作します#~Casoratian~1&

抽象代数学の分野では、の行列N  X  N行列(マップkとしての思想決定因子による乗算である→K)は、N同型K→⋀ピッキング後(マトリックスの外面乗N kはn)。Wolfram言語では、次の26バイトでこれを行うことができます

HodgeDual[TensorWedge@@#]&

そして、正の行列式に対してのみ有効なソリューションがあります。n次元の単位ハイパーキューブを取得し、それに線形変換を適用すると、結果の領域のn次元の「体積」は、変換の行列式の絶対値になります。立方体に線形変換を適用すると平行六面体が得られ、次の39バイトのコードでその体積を取得できます。

RegionMeasure@Parallelepiped[Last@#,#]&

1
これらの線に沿って私が持っていた解決策はでしたがExp@*Tr@*MatrixLog、残念ながらこれは特異行列に対しては機能しません。
ミシャラヴロフ

1
@MishaLavrovおお、それは賢い!で修正できると思いますCheck[E^Tr@MatrixLog@#,0]&
ツリーではない

それは素晴らしいことです!私はCheck以前に知りませんでした。
ミシャラヴロフ

1
少し前に、Jordan Decompositionのチャレンジを作成しました。あなたもそれに興味があるかもしれません。なんて素晴らしい答えでしょう!
メゴ

8

Haskell、71バイト

Lynnのおかげで-3バイト。別の1バイトはCraig Royのおかげです。

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

オンラインでお試しください! 最適化のためにフラグを追加しました-O。それは必要ない。

説明(古い)

f 補因子展開を再帰的に実装します。

f[[x]]=x

この行は、1 × 1行列の基本ケースをカバーしていmat[0, 0]ます。この場合、行列式はです。

f(h:t)=

これは、Haskellのパターンマッチングを使用して、マトリックスを先頭(最初の行)と末尾(マトリックスの残り)に分割します。

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

行列の先頭を列挙し(整数と先頭の無限リストを圧縮することにより)、繰り返します。

           (-1)*i*v

行列式の計算には加算と減算が交互に行われるため、インデックスが偶数かどうかに基づいて結果を否定します。

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

これは、i要素を取得し、最初の(i + 1)番目の要素が末尾のすべての行にドロップされた行と連結することにより、本質的に末尾のi番目の列を削除します。

                   *f

上記の結果の行列式を計算し、その結果に乗算し(-1)*i*vます。

       sum

上記のリストの結果を合計して返します。


2
あなたが交換する場合は、1つのバイトを救うことができるsum[(-1)^i*...foldr(-)0[...
クレイグ・ロイ

6

プロトン、99バイト

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)

オンラインでお試しください!

Mr. Xcoderの
おかげで-3バイトErik the Outgolferのおかげで-3バイト

最初の行の展開


プロトンに行列式の組み込みがないためです。
user202729

103バイト((~i%2)*2-1)->((-i%2)|1)
ミスターXcoder

また、102は交換することによってバイトj!=ij-i、またはi-j
ミスターXcoder


@EriktheOutgolferあ、はい、ありがとう!
ハイパーニュートリノ

5

オクターブ、28バイト

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

オンラインでお試しください!

これは、直交行列Qと上三角行列Rへの行列XのQR分解を使用します。Xの行列式は 、QRの行列式の積です。直交行列には単位行列式があり、三角行列の行列式は対角要素の積です。オクターブqr単一の出力で呼び出される関数はR返します。

結果は最も近い整数に丸められます。大きな入力行列の場合、浮動小数点の不正確さはエラーを超え0.5、誤った結果を生成する可能性があります。


1
それはdet組み込みを回避する興味深い方法です。;)
tomsmeding

1
@tomsmeding :-)また、それは既にStewieの答え
ルイスメンドー


5

C、 176125 バイト

42バイトのゴルフをしてくれた@ceilingcatに感謝します。また、それぞれバイトを節約してくれた@Lynnと@Jonathan Frechに感謝します。

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

ラプラス展開を使用して行列式を計算します最初の行に沿ってます。

オンラインでお試しください!

展開:

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)もう1バイト節約します。
リン

n+1+cすることができますn-~c
ジョナサンフレッチ

提案するi=s代わりにreturn s
ceilingcat

5

ゼリー、43バイト

最後に、非組み込みソリューションをゴルフ言語で記述しました!

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

バイトを保存してくれたHyperNeutrinoに感謝します!

オンラインでお試しください!(明確にするためにスペースを空けたコード)

リストからn番目の要素を削除する非常に長い方法で、後で改善されます


この答えは、HyperNeutrino、Dennis、およびLeaky Nunの答えに勝っていました。ゼリーはゴルフの言語として非常に人気があります。

簡単な説明:

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

ゼリー、24バイト

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

オンラインでお試しください!

説明

œ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のソリューションのおかげで2バイト


4

MATL、3バイト/ 5バイト

組み込み機能付き

&0|

オンラインでお試しください!

組み込みなし

ミスを指摘してくれたMisha Lavrovに感謝します。

YvpYo

オンラインでお試しください!

これにより、行列式は固有値の積として計算され、浮動小数点の不正確さを回避するために最も近い整数に丸められます。

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

特異値の積は、行列式の絶対値だけを教えてくれませんか?
ミシャラヴロフ

@MishaLavrovあなたは完全に正しいです!気づいてくれてありがとう。私は特異値の代わりに固有値を使用して修正しました...そしてそれは4バイトを節約しました\ o /
ルイス・メンドー



3

TI-Basic、2バイト

det(Ans

まぁ。

些細な答えを支持しないでください。

高校生(これらの電卓の1つを所有することを余儀なくされている)として、この機能は非常に便利です...


8
それはまだ大学で有用です-線形代数は消えません
テイラースコット

5
@TaylorScott実際には、微分方程式の復geとともに戻ってきます。
メゴ

@Mego-その通りです。何らかの理由で、彼らは私にすべての計算と線形の前にそれを許可させました:/
テイラースコット

1
@TaylorScott私の大学の数学部門による監視のため、私はそれを取ったとき、linalgはdiffeqの前提条件ではありませんでした。私の教授がそれに気づいたとき、彼はすぐに私たちにリナルで3日間のクラッシュコースを与えました。
メゴ



3

Wolfram言語(Mathematica)53 52バイト

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

オンラインでお試しください!

残念なことに、の行列演算nとすることにより、Nマトリクスこの方法は、O(使用N Nを手の届かないところに)メモリ、プット大きなテストケース。

使い方

最初の部分、1##&@@@(t=Tuples)@#は、与えられた行列の各行から項の可能なすべての積を計算します。t[Range@Tr[1^#]&/@#]要素のようなものがあり、同じ長さのリスト与え{3,2,1}たり{2,2,3}、我々は、対応する製品のために選んだ各列のエントリ言って。

Signature2番目のリストに適用します。偶数の順列をに1、奇数の順列を-1に、非順列をにマッピングします。0ます。これは、対応する製品が行列式に現れる係数です。

最後に、2つのリストのドット積を取ります。


Signature組み込みが多すぎる場合、73バイトで取得できます

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

で置き換え1##&@@Order@@@#~Subsets~{2}&ます。これは、置換の要素のすべてのペアに適用されるSignature積をとることにより、置換の可能性を計算しOrderます。Order与える1ペアは、昇順であれば-1、それは降順でだし、あれば0それらが等しいなら。


@ user202729のおかげで-1バイト


1
52バイト(場合には、あなたがこのMathematicaのゴルフ先端を知りませんでした)
user202729

私はやったが、どういうわけかここでそれを忘れていた。ありがとう!
ミシャラヴロフ

3

Pythonの3238バイト227バイト224バイト216のバイト

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

オンラインでお試しください!

私のソリューションでは、計算に行列式の定義を使用しています。残念ながら、このアルゴリズムの複雑さはn!最後のテストの通過を示すことはできませんが、理論的にはこれは可能です。


3

CJam(50 45バイト)

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

これは、スタック上の2D配列を受け取り、スタック上に整数を残す匿名ブロック(関数)です。

オンラインテストスイート

解剖

これはFaddeev-LeVerrierアルゴリズムを実装しており、そのアプローチをとる最初の答えだと思います。

目的は係数を計算することですckn×nA

pλデットλnA=k=0nckλk
cn=1c0=1nデットA

M

M00cn=1k=0MkAMk1+cnk+1cnk=1ktrAMkk=1n 

コードが直接機能することはありませんcnkMk1kcnk1k+1AMk

1kcnk=1ktr1k+1AMk1k+2AMk+1=1kcnkAA1k+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、さまざまな

ここに、SageMathでプログラムされた、私が面白いと思う行列式を計算するための多くの方法があります。ここですべて試すことができます

組み込み、3バイト

det

これはあまり面白くない。Sageは、通常はオブジェクトメソッドである多くの一般的な操作にグローバルレベルのエイリアスを提供するため、これはよりも短くなっていlambda m:m.det()ます。


固有値の積の実部、36バイト

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

残念ながら、eigenvaluesこれらはグローバルレベルのエイリアスの1つではありません。これは、Sageには関数を構成するきちんとした方法がないという事実と相まって、コストのかかるにこだわっていることを意味しますlambda。この関数は、印刷時に自動的に数値に変換される記号値であるため、一部の出力に浮動小数点の不正確さが存在する場合があります。


ヨルダン標準形式の対角の積、60バイト

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

ジョーダン標準形式では、NxN行列はブロック行列として表され、対角線上にNブロックがあります。各ブロックは、単一の固有値、または対角線に反復固有値があり1、超対角線(「メイン」対角線の右上の対角線)にsが繰り返されるMxM行列のいずれかで構成されます。これにより、主対角線上にすべての固有値(多重度)を持つ行列が作成され、1、繰り返し固有値に対応する超対角線上にのsを持つ行列になります。これは、ヨルダンの正規形の対角の積を返します。これは固有値(多重度)の積であるため、これは以前のソリューションと同じ計算を実行するより遠回りの方法です。

SageはJordan正規形が元の行列と同じリング上にあることを望んでいるため、これはすべての固有値が有理数である場合にのみ機能します。複雑な固有値はエラーになります(元の行列がリング上にない場合CDF(複雑なdouble float)またはSR)。ただし、これは、上記のソリューションと比較して、実際の部分を取得する必要がないことを意味します。


スミス分解の対角積

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

ジョーダン正規形とは異なり、スミス正規形は元の行列と同じフィールド上にあることが保証されています。Smith分解は、固有値を計算してブロック対角行列で表すのではなく、行列の基本因子を計算し(この記事では少し複雑すぎるトピックです)、対角行列に入れてD、単位のある2つの行列を計算します行列式UVそのようなD = U*A*VA元の行列です)。行列の積の行列式は行列の行列式の積(det(A*B*...) = det(A)*det(B)*...)に等しく、UおよびVは単位行列式を持つように定義されているため、det(D) = det(A)。対角行列の行列式は、単に対角要素の積です。

ラプラス拡張、109バイト

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]

これは、再帰的アプローチを使用して、最初の行に沿ってラプラス展開を実行します。det([[a]]) = a基本ケースに使用されます。det([[]]) = 1基本ケースで使用するには短くする必要がありますがその実装での私の試みには、まだ追跡できていないバグがありました。


ライプニッツの式、100バイト

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

これは、ライプニッツの公式を直接実装しています。数式のはるかに良い説明と、私がおそらく書くことができるよりもなぜそれが機能するかについては、この素晴らしい答えを参照してください。


の実部e^(Tr(ln(M)))、48バイト

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

この関数は、シンボリック式を返します。数値近似を取得するには、n(result)印刷する前に呼び出します。

これは、誰もまだ使用したことのないアプローチです。これについては、より長く、より詳細な説明をします。

ましょうA実数上の正方行列になります。定義により、の決定要因Aはの固有値の積に等しくなりAます。のトレースはの固有値のA合計に等しくなりAます。実数の場合r_1r_2exp(r_1) * exp(r_2) = exp(r_1 + r_2)。以来、行列指数関数が(特に前のアイデンティティに)スカラー指数関数に類似であると定義され、そしてマトリックス指数は行列を対角化し、対角線上の固有値にスカラー指数関数を適用することによって計算することができる、我々が言うことができますdet(exp(A)) = exp(trace(A))(のexp(λ)各固有値λA積は、の固有値の合計に等しいexp(A))。したがって、行列を見つけることができればことができますLようなexp(L) = A、計算できdet(A) = exp(trace(L))ます。

このような行列を見つけることができます L計算によりlog(A)。行列の対数は、行列の指数関数と同じ方法で計算できます。スカラー対数関数を各固有値に適用して正方対角行列を形成しますA(これがA実数に制限されている理由です)。のトレースのみLを考慮するため、構築をスキップして、固有値の指数を直接合計することができます。行列が複素環上にない場合でも、固有値は複素数になる可能性があるため、合計の実数部を使用します。


1
最後の部分は魅力的なアイデアですが、ヘッダーと説明はコードと一致せず、マトリックスの対数をとりません。それはちょうどreal(prod(m.eigenvalues()))手に負えないです。
ピーターテイラー

2

Java 8、266 261 259 258バイト

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

お母さん、ビルトインなし。 。Javaにはないためです。..>。>

-7バイトのおかげで @ceilingcatの

説明:

ここで試してみてください。(最後のテストケースのみが大きすぎてlongサイズ2 63 -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

再帰ラプラス

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)

少ないゴルフ

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

テスト

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バイト
Arnauld

または、空の行列をサポートする85バイト(行列式は1でなければなりません)。
アーナルド

(私はあなたから派生したこの回答で同じ最適化を使用しました。)
アーナルド




1

Java(OpenJDK 8)195 192 177バイト

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

オンラインでお試しください!

他の多くの答えと同様に、これもラプラスの公式を使用しています。やや少ないゴルフバージョン:

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.