정수 행렬의 결정자


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


지원해야하는 최대 크기의 매트릭스가 있습니까, 아니면 임의입니까?
Taylor Scott

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

3
당신은 당신이 4 개의 젤리 답변을 연속적으로 서로 아웃 골핑 할 때 흥미로운 도전을 알고 있습니다 ...
완전히 인간적인

답변:


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

작동하는 이유-Mathy 버전

연산자 det 는 행렬을 취하고 스칼라를 반환합니다. N -by- N의 행렬의 집합으로 간주 될 수 N 길이의 벡터 N 있도록 DET가 취하는 함수 정말 N ℤ로부터 벡터 n은 스칼라 및 반환.

따라서 det [ v 1 v 2 v 3 ... v n ]에 대해 det ( v 1 , v 2 , v 3 , ..., v n )를 작성 합니다.

공지 것을 DET는 각각 인수 선형, 즉 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 ). 따라서 (ℤ n ) n 의 선형 맵입니다. ℤ.

선형 맵에서 기본 이미지를 결정하면 충분합니다. (ℤ 용의 기초 N ) n은 구성 N ℤ의 기본 요소 -fold 텐서 제품 N , E ieeg 5 ⊗ 예 3 ⊗ 예 1 ⊗ 예 5 ⊗ 예 1 . 두 열이 동일한 행렬의 행렬식이 0이므로 동일한 텐서가 포함 된 텐서 제품을 0으로 보내야합니다. 별개의 기본 요소의 텐서 제품이 전송되는 것을 확인해야합니다. 텐서 곱에서 벡터의 인덱스는 bijection, 즉 순열을 형성하는데,이 순열은 심지어 순열도 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)이 있으므로 순열이 홀수입니다.

각 전치 (두 요소를 교환)는 하나의 반전을 추가하거나 하나의 반전을 제거하여 반전 수의 패리티를 바꾸고 순열의 패리티는 순열을 달성하는 데 필요한 조옮김 수의 패리티입니다.

결론적으로 우리의 공식은 다음과 같습니다.

왜 작동합니까?

여기서 σ는 n 문자 에 대한 모든 순열의 그룹 𝕊 n 의 순열 이며, sgn 은 순열의 부호이며, AKA (-1)은 순열의 패리티로 올렸으며 , ij 는 ( ij ) 번째 항목입니다. 행렬 ( i down, j across).


17
그 "비 수학적인 버전"은 꽤 지독한 수학입니다.
MD XF

6
@MDXF 공식과 기호 및 숫자는 수학을 거의 구성하지 않습니다. 수학은 추상화와 일반화 그리고 기호의 형식적인 조작에 대한 논리입니다.
Leaky Nun

7
@JAB Jelly는 자체 사용자 정의 코드 페이지를 구현 합니다 . (요즘, TIO는 코드 페이지에 대한 링크를 포함 할 것입니다 ...)
완전히 인간적인

1
@Mego "대각선 곱"은 1x1, 2x2 및 3x3 행렬에서만 작동합니다. 더 큰 행렬의 경우 모든 순열과 해당 패리티를 고려해야합니다.
Leaky Nun

3
"이 공식은 abcxyz 페이지에 나열되어 있기 때문에 사실이어야합니다"라고 말하는 대신 실제로 게시물에 증명을 포함하려면 +1입니다 .
user202729 5

11

R , 3 바이트

사소한 솔루션

det

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

R , 94 92 바이트

재 구현 된 솔루션

Jarko Dubbeldam에 의해 outgolfed

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ß-Ƥ$Ṛḅ-

Laplace 확장을 사용합니다 . 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

14에서 42 바이트 사이의 Wolfram Language (Mathematica)

우리는 내장 을 완전히 피하는 3 바이트 내장53 바이트 솔루션 을 가지고 있으므로 여기에 어딘가에있는 더 이상한 솔루션이 있습니다.

볼프람 언어가 많은 간단한 구조로 다른 행렬의 제품으로 행렬을 분해 매우 강렬 기능을. 가장 간단한 것 중 하나 (이전에 들어 본 것을 의미 함)는 요르단 분해입니다. 모든 행렬은 해당 행렬의 요르단 분해라고하는 특정 구조의 대각선 블록으로 구성된 (복잡한 값을 갖는) 상단 삼각 행렬과 유사합니다. 유사성은 결정자를 유지하며, 삼각 행렬의 결정자는 대각선 요소의 곱이므로 다음 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이지만 불행히도 이것은 단일 행렬에는 작동하지 않습니다.
Misha Lavrov

1
@MishaLavrov Ooh, 영리하다! 나는 당신이 그것을 고칠 수 있다고 생각합니다 Check[E^Tr@MatrixLog@#,0]&.
나무가 아님

대단해! 나는 Check전에는 몰랐다 .
Misha Lavrov

1
얼마 전에 Jordan 분해에 도전했습니다 . 당신도 그것에 관심이있을 수 있습니다. 정말 좋은 답변입니다!
Mego

8

하스켈 , 71 바이트

Lynn 덕분에 -3 바이트. 크레이그 로이 덕분에 또 하나의 먼지가 먼지입니다.

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 바이트 Outgofer Erik 덕분에 -3 바이트

첫 번째 행을 통한 확장


양성자가 결정 요인을 내장하지 않았기 때문입니다.
user202729

103 바이트 . ((~i%2)*2-1)->((-i%2)|1)
Mr. Xcoder

또는 로 교체 j!=i하여 102 바이트 . j-ii-j
Mr. Xcoder


@EriktheOutgolfer 아 그래, 고마워!
HyperNeutrino

5

옥타브 , 28 바이트

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

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

이것은 행렬 X 의 직교 행렬 Q 및 상부 삼각 행렬 R 로의 QR 분해 를 사용한다 . 결정의 X는 의 이들의 제품 QR . 직교 행렬은 단위 결정자를 가지며, 삼각 행렬의 경우 결정자는 대각선 항목의 곱입니다. 단일 출력으로 호출 된 옥타브의 함수는 R을 제공합니다 .qr

결과는 가장 가까운 정수로 반올림됩니다. 큰 입력 행렬의 경우 부동 소수점 부정확성이 오류를 초과 0.5하여 잘못된 결과를 생성 할 수 있습니다.


1
그것은 det내장 을 피하는 흥미로운 방법 입니다. ;)
tomsmed

1
@tomsmeding :-) 또한, 그것은 Stewie의 답변
Luis Mendo


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 바이트를 더 저장합니다.
Lynn

n+1+c일 수 있습니다 n-~c.
Jonathan Frech

i=s대신 추천return s
천장 고양이

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

특이 값의 곱이 결정자의 절대 값만을 나타내지 않습니까?
Misha Lavrov

@MishaLavrov 당신 말이 맞아요! 알아 주셔서 감사합니다. 내가 대신 특이 값의 고유 값을 사용하여 수정 ... 그 저장 4 바이트 \ O /
루이스 Mendo


4

젤리 , 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.


3

TI 기본, 2 바이트

det(Ans

사소한 답변을 찬성하지 마십시오.

고등학생 (이 계산기 중 하나를 소유해야 함) 으로서이 기능은 매우 유용합니다 ...


8
그것은 여전히 ​​대학에서 유용합니다-선형 대수는 사라지지 않습니다
Taylor Scott

5
@TaylorScott 사실, 그것은 미분 방정식에서 복수로 돌아옵니다.
Mego

@ Mego-당신이 맞습니다; 어떤 이유로 그들이 할 수 있지만 나 선형 전에 CALC의 모든 그 걸릴 : /
테일러 스콧

1
@TaylorScott 내 대학의 수학 부서의 감독으로 인해 linalg는 diffeq를 전제 조건으로하지 않았습니다. 교수님이 그 사실을 깨달았을 때, 그는 linalg에서 3 일 동안의 크래쉬 코스를 빠르게주었습니다.
Mego

3

하스켈, 62 바이트

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

온라인으로 사용해보십시오! (@totallyhuman의 솔루션에서 가져온 테스트 케이스가있는 스쿠터.)

d첫 번째 열을 따라 Laplace 확장을 사용하여 결정자를 계산합니다. 영구적 인 것보다 3 바이트 더 필요합니다 .



3

Wolfram Language (Mathematica) , 53 52 바이트

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

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

불행히도, 이런 식으로 n x n 행렬 의 행렬식을 계산하는 것은 O ( n n ) 메모리를 사용하므로 큰 테스트 사례에 도달하지 못합니다.

작동 원리

첫 번째 부분 1##&@@@(t=Tuples)@#은 주어진 행렬의 각 행에서 항의 모든 가능한 곱을 계산합니다. t[Range@Tr[1^#]&/@#]요소와 같은 것들 같은 길이의 목록 제공 {3,2,1}또는 {2,2,3}우리가 해당 제품에 대한 골라 각 행의 어느 항목을 말을.

Signature두 번째 목록에 적용 합니다.이 목록은 순열도 1, 홀수 순열은 -1, 비 순열은로 매핑 합니다 0. 이것은 정확하게 해당 제품이 결정 요인에 나타나는 계수입니다.

마지막으로 두 목록의 내적을 구합니다.


해도 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 바이트 (경우에 당신이 티카 골프 팁을 몰랐다)
user202729

나는했지만 어떻게 든 잊어 버렸습니다. 감사!
Misha Lavrov

3

파이썬 3 , 238 바이트 , 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(λ)det(λInA)=k=0nckλk
cn=1c0=(1)ndetA

계수는 보조 행렬 dint에 의해 위에서 아래로 재귀 적으로 결정됩니다M

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

cnkMk(1)kcnk(1)k+1AMk

(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 , 다양한

SageMath에 프로그래밍 된 흥미로운 결정 요인을 계산하는 방법은 다음과 같습니다. 그들은 모두 여기에서 시도 할 수 있습니다 .

내장, 3 바이트

det

이건 너무 재미 있지 않습니다. Sage는 일반적으로 오브젝트 메소드 인 많은 공통 조작에 글로벌 레벨 별명을 제공하므로이 값은보다 짧습니다 lambda m:m.det().


고유 값 곱의 실제 부분, 36 바이트

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

불행히도, eigenvalues글로벌 수준의 별칭 중 하나가 아닙니다. 즉, Sage가 기능을 깔끔하게 구성 할 수있는 방법이 없다는 사실과 함께 비용이 많이 듭니다 lambda. 이 기능은 인쇄시 자동으로 숫자 값으로 변환되는 기호 값이므로 일부 출력에 일부 부동 소수점 부정확성이 존재할 수 있습니다.


요르단 표준형의 대각선 곱, 60 바이트

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

Jordan Normal 형식에서 NxN 행렬은 대각선에 N 개의 블록이있는 블록 행렬로 표시됩니다. 각 블록은 단일 고유 값 또는 대각선과 반복되는 고유 값이 대각 1대각선 ( "주"대각선의 위와 오른쪽)에 반복되는 고유 값으로 구성된 MxM 행렬로 구성 됩니다. 이로 인해 주 대각선에 모든 고유 값 (다중성 포함)이 있고 일부 1고유 값이 반복 고유 값에 해당하는 대각 대각선 이있는 행렬이 생성됩니다 . 이 값은 고유 값 (곱하기)의 곱인 요르단 정규형의 대각선 곱을 반환하므로 이전 솔루션과 동일한 계산을 수행하는보다 간단한 방법입니다.

Sage는 Jordan 정규 형식이 원래 행렬과 동일한 고리 위에 있기를 원하므로 모든 고유 값이 합리적인 경우에만 작동합니다. 복소수 고유 값으로 인해 원래 행렬이 링 CDF(복수 수 부동 소수점) 또는을 초과하지 않는 한 오류가 발생 SR합니다. 그러나 이것은 위의 솔루션과 비교하여 실제 부분을 취하는 것이 필요하지 않음을 의미합니다.


스미스 분해에서 대각선의 곱

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

Jordan 정규 형식과 달리 Smith 정규 형식은 원래 행렬과 동일한 필드 위에 있어야합니다. Smith 분해는 고유 값을 계산하고이를 블록 대각 행렬로 표시하는 대신 행렬의 기본 제수 (이 게시물에 대해 너무 복잡한 주제)를 D계산 하고 대각 행렬 에 넣고 단위를 사용하여 두 개의 행렬을 계산합니다. 결정 UV그 와 같은 것 D = U*A*V( A원래 행렬이있는 곳 ). 행렬 곱의 행렬식이 행렬 ( det(A*B*...) = det(A)*det(B)*...) 행렬식의 곱 UV같고 단위 결정자를 갖도록 정의되기 때문 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]

재귀 적 접근 방식을 사용하여 첫 번째 행을 따라 Laplace 확장을 수행합니다. 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_2, exp(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

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

엄마가 없어 보인다. 자바가 없기 때문에 ..>.>

@ceilingcat 덕분에 -7 바이트 .

설명:

여기에서 시도하십시오. (마지막 테스트 케이스 만 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

자바 스크립트 (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 이어야 함 )
Arnauld

(나는 당신의 것에서 파생 된 이 답변 에서 동일한 최적화를 사용했습니다 .)
Arnauld




1

자바 (오픈 JDK 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;}

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

다른 많은 답변과 마찬가지로 Laplace 수식도 사용합니다. 약간 덜 골프 버전 :

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.