Determinante de una matriz entera


34

Dada una matriz entera cuadrada como entrada, genera el determinante de la matriz.

Reglas

  • Puede suponer que todos los elementos en la matriz, el determinante de la matriz y el número total de elementos en la matriz están dentro del rango representable de enteros para su idioma.
  • Se permite emitir un valor decimal / flotante con una parte fraccional de 0 (por ejemplo, en 42.0lugar de 42).
  • Las acumulaciones están permitidas, pero le recomendamos que incluya una solución que no las use.

Casos de prueba

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


¿Hay un tamaño máximo de matriz que necesita ser soportado o es arbitrario?
Taylor Scott

1
@TaylorScott Primera regla enumerada: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

44
Sabes que tienes un desafío interesante cuando tienes 4 respuestas de Jelly superadas consecutivamente entre sí ...
Totalmente humano

Respuestas:


25

Jalea , 15 bytes

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

Pruébalo en línea!

Cómo funciona

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

Por qué funciona - versión mathy

El operador det toma una matriz y devuelve un escalar. Una matriz n -by- n puede considerarse como una colección de n vectores de longitud n , por lo que det es realmente una función que toma n vectores de ℤ n y devuelve un escalar.

Por lo tanto, escribo det ( v 1 , v 2 , v 3 , ..., v n ) para det [ v 1 v 2 v 3 ... v n ].

Observe que det es lineal en cada argumento, es decir, 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 ). Por lo tanto, es un mapa lineal de (ℤ n ) n a ℤ.

Es suficiente determinar la imagen de la base bajo el mapa lineal. La base de (ℤ n ) n consiste en productos tensor n- pliegues de los elementos básicos de ℤ n , es decir, ee 5 ⊗ e 3 ⊗ e 1 ⊗ e 5 ⊗ e 1 . Los productos tensores que incluyen tensores idénticos deben enviarse a cero, ya que el determinante de una matriz en la que dos columnas son idénticas es cero. Queda por comprobar a qué se envían los productos tensoriales de elementos básicos distintos. Los índices de los vectores en el producto tensor forman una biyección, es decir, una permutación, en la cual las permutaciones pares se envían a 1 y las permutaciones impares se envían a -1.

Por ejemplo, para encontrar el determinante de [[1, 2], [3, 4]]: tenga en cuenta que las columnas son [1, 3] y [2, 4]. Descomponemos [1, 3] para dar (1 e 1 + 3 e 2 ) y (2 e 1 + 4 e 2 ). El elemento correspondiente en el producto tensor es (1 e 1 ⊗ 2 e 1 + 1 e 1 ⊗ 4 e 2 + 3 e 2 ⊗ 2 e 1 + 3 e 2 ⊗ 4 e 2 ), que simplificamos a (2 e 1 ⊗ e 1 + 4 e 1 ⊗ e 2 + 6 e 2 ⊗ e 1 + 12 e 2 ⊗ e 2) Por lo tanto:

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

Ahora queda por demostrar que la fórmula para encontrar la paridad de la permutación es válida. Lo que hace mi código es esencialmente encontrar el número de inversiones, es decir, los lugares donde un elemento a la izquierda es más grande que un elemento a la derecha (no necesariamente consecutivamente).

Por ejemplo, en la permutación 3614572, hay 9 inversiones (31, 32, 61, 64, 65, 62, 42, 52, 72), por lo que la permutación es impar.

La justificación es que cada transposición (intercambiando dos elementos) agrega una inversión o quita una inversión, intercambiando la paridad del número de inversiones, y la paridad de la permutación es la paridad del número de transposiciones necesarias para lograr la permutación.

Por lo tanto, en conclusión, nuestra fórmula viene dada por:

Por qué funciona - versión no matemática

donde σ es una permutación de 𝕊 n el grupo de todas las permutaciones de n cartas, y sgn es la señal de la permutación, AKA (-1) elevado a la paridad de la permutación, y un ij es el ( ij ) º entrada en la matriz ( i abajo, j a través).


17
Esa "versión no matemática" es bastante maldita.
MD XF

66
Las fórmulas, los símbolos y los números de @MDXF difícilmente constituyen matemáticas. La matemática es la abstracción y la generalización y la lógica detrás de las manipulaciones formales de los símbolos.
Leaky Nun

77
@JAB Jelly implementa su propia página de códigos personalizada . (Uno de estos días, TIO incluirá un enlace a la página de códigos ...)
totalmente humano

1
@Mego, la "suma de productos diagonales" solo funciona para matrices 1x1, 2x2 y 3x3. Para matrices más grandes, debe considerar todas las permutaciones y su paridad.
Leaky Nun

3
+1 para incluir realmente la prueba en la publicación en lugar de decir "debido a que esta fórmula aparece en la página abcxyz, debe ser verdadera".
user202729

11

R , 3 bytes

Solución trivial

det

Pruébalo en línea!

R , 94 92 bytes

solución re-implementada

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

Pruébalo en línea!

Utiliza de forma recursiva la expansión de menores en la primera columna de la matriz.

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

Jalea , 16 15 12 10 bytes

Ḣ×Zß-Ƥ$Ṛḅ-

Utiliza la expansión de Laplace . ¡Gracias a @miles por jugar 3 5 bytes!

Pruébalo en línea!

Cómo funciona

Ḣ×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 Language (Mathematica) , entre 14 y 42 bytes

Hemos tenido una solución integrada de 3 bytes y una solución de 53 bytes que evita por completo las incorporaciones, por lo que aquí hay algunas soluciones más extrañas en algún punto intermedio.

Wolfram Language tiene muchas funciones muy intensas para descomponer matrices en productos de otras matrices con una estructura más simple. Uno de los más simples (lo que significa que he oído hablar de él antes) es la descomposición de Jordan. Cada matriz es similar a una matriz triangular superior (posiblemente de valor complejo) hecha de bloques diagonales con una estructura específica, llamada la descomposición de Jordan de esa matriz. La similitud preserva los determinantes, y el determinante de una matriz triangular es el producto de los elementos diagonales, por lo que podemos calcular el determinante con los siguientes 42 bytes :

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

El determinante también es igual al producto de los valores propios de una matriz, con multiplicidad. Afortunadamente, la función de valor propio de Wolfram realiza un seguimiento de la multiplicidad (incluso para matrices no diagonalizables), por lo que obtenemos la siguiente solución de 20 bytes :

1##&@@Eigenvalues@#&

La siguiente solución es hacer trampa y no estoy seguro de por qué funciona. El wronskiano de una lista de n funciones es el determinante de la matriz de las primeras n -1 derivadas de las funciones. Si le damos a la Wronskianfunción una matriz de enteros y decimos que la variable de diferenciación es 1, de alguna manera escupe el determinante de la matriz. Es raro, pero no involucra las letras " Det" y solo tiene 14 bytes ...

#~Wronskian~1&

(El determinante Casoratian funciona tan bien, de 1 byte más: #~Casoratian~1&)

En el ámbito de la álgebra del extracto, el determinante de un n  x  n de la matriz (idea de que el mapa k → k que es la multiplicación por el factor determinante) es la n ésima potencia exterior de la matriz (después de recoger un isomorfismo k → ⋀ n k n ) En el lenguaje Wolfram, podemos hacer esto con los siguientes 26 bytes :

HodgeDual[TensorWedge@@#]&

Y aquí hay una solución que funciona solo para determinantes positivos. Si tomamos un hipercubo de unidad n- dimensional y le aplicamos una transformación lineal, el "volumen" n- dimensional de la región resultante es el valor absoluto del determinante de la transformación. Aplicar una transformación lineal a un cubo da un paralelepípedo, y podemos tomar su volumen con los siguientes 39 bytes de código:

RegionMeasure@Parallelepiped[Last@#,#]&

1
La solución que tuve en este sentido fue Exp@*Tr@*MatrixLog, pero desafortunadamente esto no funciona para matrices singulares.
Misha Lavrov

1
@MishaLavrov Ooh, eso es inteligente! Creo que puedes arreglarlo con Check[E^Tr@MatrixLog@#,0]&.
No es un árbol

¡Eso es genial! No había estado al tanto Checkantes.
Misha Lavrov

1
Creé un desafío para Jordan Decomposition hace un tiempo. Puede que también te interese. ¡Qué gran respuesta!
Mego

8

Haskell , 71 bytes

-3 bytes gracias a Lynn. Otro bytes el polvo gracias a Craig Roy.

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

Pruébalo en línea! Se agregó una -Obandera para fines de optimización. No es necesario.

Explicación (obsoleta)

f implementa recursivamente la expansión del cofactor.

f[[x]]=x

Esta línea cubre el caso base de una matriz 1 × 1 , en cuyo caso el determinante es mat[0, 0].

f(h:t)=

Esto utiliza la coincidencia de patrones de Haskell para dividir la matriz en una cabeza (la primera fila) y una cola (el resto de la matriz).

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

Enumera la cabeza de la matriz (comprimiendo la lista infinita de números enteros y la cabeza) e itera sobre ella.

           (-1)*i*v

Niegue el resultado en función de si su índice es uniforme, ya que el cálculo del determinante implica sumas y restas alternadas.

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

Esto esencialmente elimina la i-ésima columna de la cola al tomar i elementos y concatenarla con la fila con los primeros (i + 1) th elementos eliminados para cada fila en la cola.

                   *f

Calcule el determinante del resultado anterior y multiplíquelo con el resultado de (-1)*i*v.

       sum

Suma el resultado de la lista anterior y devuélvelo.


2
podría guardar 1 byte si reemplaza el sum[(-1)^i*...confoldr(-)0[...
Craig Roy

6

Protón , 99 bytes

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)

Pruébalo en línea!

-3 bytes gracias al Sr. Xcoder
-3 bytes gracias a Erik the Outgolfer

Expansión sobre la primera fila


Solo porque Proton no tiene incorporado como determinante.
usuario202729

103 bytes . ((~i%2)*2-1)->((-i%2)|1)
Sr. Xcoder

También 102 bytes reemplazando j!=icon j-io i-j.
Sr. Xcoder


@EriktheOutgolfer Ah sí, gracias!
HyperNeutrino

5

Octava , 28 bytes

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

Pruébalo en línea!

Esto utiliza la descomposición QR de una matriz X en una matriz orthgonal Q y una matriz triangular superior R . El determinante de X es el producto de los de Q y R . Una matriz ortogonal tiene un determinante unitario, y para una matriz triangular, el determinante es el producto de sus entradas diagonales. De Octave qrfunción llamada con una sola salida da R .

El resultado se redondea al entero más cercano. Para matrices de entrada grandes, las imprecisiones de coma flotante pueden producir un error superior 0.5y, por lo tanto, producir un resultado incorrecto.


1
Esa es una forma interesante de evadir el detedificio. ;)
tomsmeding

1
@tomsmeding :-) Además, ya se había "usado" en la respuesta de Stewie
Luis Mendo


5

C,  176125  bytes

¡Gracias a @ceilingcat por jugar 42 bytes y gracias a @Lynn y @Jonathan Frech por guardar un byte cada uno!

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

Calcula el determinante utilizando la expansión de Laplace a lo largo de la primera fila.

Pruébalo en línea!

Desenrollado:

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)guarda un byte más.
Lynn

n+1+cpuede ser n-~c.
Jonathan Frech

Sugerir en i=slugar dereturn s
ceilingcat

5

Jalea , 43 bytes

¡Finalmente terminé de escribir mi solución no incorporada en un lenguaje de golf!

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

¡Gracias a HyperNeutrino por guardar un byte!

Pruébalo en línea! (código espaciado para mayor claridad)

La forma terriblemente larga de eliminar elementos n-ésimo de una lista, mejorará más tarde


Esta respuesta había sido superada por las respuestas de HyperNeutrino, Dennis y Leaky Nun. Jelly es muy popular como lenguaje de golf.

Explicación rápida:

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

Jalea , 24 bytes

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

Pruébalo en línea!

Explicación

œ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 bytes gracias a la solución user202729


4

MATL , 3 bytes / 5 bytes

Con función incorporada

&0|

Pruébalo en línea!

Sin incorporado

Gracias a Misha Lavrov por señalar un error, ahora corregido

YvpYo

Pruébalo en línea!

Esto calcula el determinante como el producto de los valores propios, redondeado al entero más cercano para evitar imprecisiones de punto flotante.

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

¿El producto de los valores singulares no le indicaría el valor absoluto del determinante?
Misha Lavrov

@MishaLavrov Tienes toda la razón! Gracias por notarlo. Lo corregí usando valores propios en lugar de valores singulares ... y eso ahorró 4 bytes \ o /
Luis Mendo

4

R , 32 bytes

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

Utiliza el algoritmo de Not a Tree para tomar los valores propios de la matriz y tomar la parte real de su producto.

Pruébalo en línea!


¡Muy elegante! +1.
Giuseppe

3

Octava , 30 bytes

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

Pruébalo en línea!

o la solución aburrida de 4 bytes (ahorró 6 bytes gracias a Luis Mendo (olvidó las reglas que regulan las funciones integradas)):

@det

Explicación:

¡Subiendo! :)


3

TI-Basic, 2 bytes

det(Ans

Ah bueno.

Por favor, no voten por respuestas triviales.

Como estudiante de secundaria (que se ve obligado a tener una de estas calculadoras), esta función es muy útil, así que ...


8
Todavía es muy útil en la universidad: el álgebra lineal no desaparece
Taylor Scott

55
@TaylorScott De hecho, vuelve con una venganza en las ecuaciones diferenciales.
Mego

@Mego: tienes razón en eso; aunque por alguna razón me dejaron tomar todo el cálculo y eso antes que lineal: /
Taylor Scott

1
@TaylorScott Debido a un descuido del departamento de matemáticas de mi universidad, linalg no era un requisito previo para diffeq cuando lo tomé. Cuando mi profesor se dio cuenta de eso, rápidamente nos dio un curso intensivo de 3 días en linalg.
Mego

3

Haskell, 62 bytes

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

Pruébalo en línea! (Pie de página con casos de prueba tomados de la solución @ totallyhuman).

dcalcula el determinante usando una expansión de Laplace a lo largo de la primera columna. Necesita tres bytes más que el permanente .



3

Wolfram Language (Mathematica) , 53 52 bytes

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

Pruébalo en línea!

Desafortunadamente, calcular el determinante de una matriz n por n de esta manera utiliza la memoria O ( n n ), lo que pone fuera del alcance los casos de prueba grandes.

Cómo funciona

La primera parte, 1##&@@@(t=Tuples)@#calcula todos los productos posibles de un término de cada fila de la matriz dada. t[Range@Tr[1^#]&/@#]da una lista de la misma longitud cuyos elementos son similares {3,2,1}o {2,2,3}dicen qué entrada de cada fila elegimos para el producto correspondiente.

Aplicamos Signaturea la segunda lista, que asigna permutaciones pares a 1, permutaciones impares a -1, y no permutaciones a 0. Este es precisamente el coeficiente con el que el producto correspondiente aparece en el determinante.

Finalmente, tomamos el producto escalar de las dos listas.


Si incluso Signaturees demasiado incorporado, a 73 bytes podemos tomar

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

reemplazándolo por 1##&@@Order@@@#~Subsets~{2}&. Esto calcula Signatureuna posible permutación tomando el producto de Orderaplicado a todos los pares de elementos de la permutación. Orderdará 1si el par está en orden ascendente, -1si está en orden descendente y 0si son iguales.


-1 byte gracias a @ user202729


1
52 bytes (en caso de que no sabía este consejo golf Mathematica)
user202729

Lo hice, pero de alguna manera lo olvidé aquí. ¡Gracias!
Misha Lavrov

3

Python 3 , 238 bytes , 227 bytes , 224 bytes , 216 bytes

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

Pruébalo en línea!

Mi solución utiliza la definición de un determinante para los cálculos. Desafortunadamente, la complejidad de este algoritmo es n!y no puedo mostrar el paso de la última prueba, pero en teoría esto es posible.


3

CJam ( 50 45 bytes)

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

Este es un bloque anónimo (función) que toma una matriz 2D en la pila y deja un número entero en la pila.

Conjunto de pruebas en línea

Disección

Esto implementa el algoritmo Faddeev-LeVerrier , y creo que es la primera respuesta para adoptar ese enfoque.

ckn×nA

p(λ)det(λInA)=k=0nckλk
cn=1c0=(1)ndetA

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 , varios

Aquí hay un montón de métodos para calcular el determinante que encontré interesante, todos programados en SageMath. Todos pueden ser probados aquí .

Construido, 3 bytes

det

Este no es demasiado interesante. Sage proporciona alias de nivel global a muchas operaciones comunes que normalmente serían métodos de objeto, por lo que es más corto que lambda m:m.det().


Parte real del producto de valores propios, 36 bytes

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

Desafortunadamente, eigenvaluesno es uno de esos alias a nivel global. Eso, combinado con el hecho de que Sage no tiene una forma ordenada de componer funciones, significa que estamos atrapados en un proceso costoso lambda. Los valores simbólicos de esta función se convierten automáticamente en valores numéricos cuando se imprimen, por lo que puede haber alguna inexactitud de coma flotante en algunas salidas.


Producto de Diagonal en forma normal Jordan, 60 bytes

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

En la forma Jordan Normal, una matriz NxN se representa como una matriz de bloques, con N bloques en la diagonal. Cada bloque consta de un valor propio único o una matriz MxM con un valor propio repetido en la diagonal 1ys en la super-diagonal (la diagonal arriba y a la derecha de la diagonal "principal"). Esto da como resultado una matriz con todos los valores propios (con multiplicidad) en la diagonal principal, y algunos 1s en la super-diagonal correspondiente a los valores propios repetidos. Esto devuelve el producto de la diagonal de la forma normal de Jordan, que es el producto de los valores propios (con multiplicidad), por lo que esta es una forma más indirecta de realizar el mismo cálculo que la solución anterior.

Como Sage quiere que la forma normal de Jordan esté sobre el mismo anillo que la matriz original, esto solo funciona si todos los valores propios son racionales. Los valores propios complejos dan como resultado un error (a menos que la matriz original esté sobre el anillo CDF(flotadores dobles complejos) o SR). Sin embargo, esto significa que tomar la parte real no es necesario, en comparación con la solución anterior.


Producto de la Diagonal en la descomposición de Smith

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

A diferencia de la forma normal de Jordan, se garantiza que la forma normal de Smith estará sobre el mismo campo que la matriz original. En lugar de calcular los valores propios y representarlos con una matriz diagonal de bloque, la descomposición de Smith calcula los divisores elementales de la matriz (que es un tema demasiado complicado para esta publicación), los coloca en una matriz diagonal Dy calcula dos matrices con unidad determinante Uy Vtal que D = U*A*V(donde Aestá la matriz original). Desde el determinante del producto de matrices es igual al producto de los determinantes de las matrices ( det(A*B*...) = det(A)*det(B)*...), y Uy Vse definen para tener determinantes de la unidad, det(D) = det(A). El determinante de una matriz diagonal es simplemente el producto de los elementos en la diagonal.

Expansión de Laplace, 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]

Esto realiza la expansión de Laplace a lo largo de la primera fila, utilizando un enfoque recursivo. det([[a]]) = ase usa para el caso base. Debería ser más corto de usar det([[]]) = 1para el caso base, pero mi intento en esa implementación tenía un error que aún no he podido rastrear.


Fórmula de Leibniz, 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()))

Esto implementa directamente la fórmula de Leibniz. Para una explicación mucho mejor de la fórmula y por qué funciona de lo que posiblemente podría escribir, vea esta excelente respuesta .


Parte real de e^(Tr(ln(M)))48 bytes

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

Esta función devuelve expresiones simbólicas. Para obtener una aproximación numérica, llame n(result)antes de imprimir.

Este es un enfoque que no he visto a nadie usar todavía. Voy a dar una explicación más larga y más detallada de esta.

Dejar Aser una matriz cuadrada sobre los reales. Por definición, el determinante de Aes igual al producto de los valores propios de A. La traza de Aes igual a la suma de Alos valores propios. Para los números reales r_1y r_2, exp(r_1) * exp(r_2) = exp(r_1 + r_2). Dado que la función exponencial de la matriz se define como análoga a la función exponencial escalar (especialmente en la identidad anterior), y la exponencial de la matriz se puede calcular diagonalizando la matriz y aplicando la función exponencial escalar a los valores propios en la diagonal, podemos decir det(exp(A)) = exp(trace(A))(el producto de exp(λ)para cada valor propio λde Aes igual a la suma de los valores propios de exp(A)). Por lo tanto, si podemos encontrar una matriz Ltal queexp(L) = A, podemos calcular det(A) = exp(trace(L)).

Podemos encontrar dicha matriz Lmediante la computación log(A). El logaritmo de la matriz se puede calcular de la misma manera que la matriz exponencial: forma una matriz diagonal cuadrada aplicando la función de logaritmo escalar a cada valor propio de A(es por eso que restringimos Aa los reales). Como solo nos preocupamos por el rastro de L, podemos omitir la construcción y simplemente sumar directamente los exponenciales de los valores propios. Los valores propios pueden ser complejos, incluso si la matriz no está sobre el anillo complejo, por lo que tomamos la parte real de la suma.


1
La última parte es una idea fascinante, pero el encabezado y la explicación no coinciden con el código, que no toma un logaritmo matricial. Simplemente no tiene real(prod(m.eigenvalues()))golf.
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;}

Mira mamá, no hay complementos ... porque Java no tiene ninguno ...>.>

-7 bytes gracias a @ceilingcat .

Explicación:

Pruébalo aquí (Solo el último caso de prueba es demasiado grande para caber en un longtamaño de 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

Laplace recursiva

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)

Menos golf

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

Prueba

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 con el mismo comportamiento
Arnauld

O 85 bytes para soportar la matriz vacía (cuyo determinante debe ser 1 ).
Arnauld

(Usé las mismas optimizaciones en esta respuesta , que se deriva de la suya.)
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;}

Pruébalo en línea!

Como muchas otras respuestas, esto también usa la fórmula de Laplace. Una versión un poco menos golfizada:

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.