Детермінанта цілої матриці


34

Враховуючи квадратну цілочисельну матрицю як вхід, виведіть визначник матриці.

Правила

  • Ви можете припустити, що всі елементи в матриці, детермінант матриці та загальна кількість елементів у матриці знаходяться в межах репрезентативного діапазону цілих чисел для вашої мови.
  • Дозволяється виводити значення десяткової / поплавкової частини з дробовою частиною 0 (наприклад, 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 відповіді з
желей, які послідовно перевертають

Відповіді:


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 бере матрицю і повертає скаляр. An 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- кратних тензорних добутків базових елементів ℤ n , т. Е. E 5 ⊗ e 3 ⊗ e 1 ⊗ e 5 ⊗ e 1 . Продукти тензора, що включають однакові тензори, повинні надсилатися до нуля, оскільки визначник матриці, в якій два стовпчики однакові, дорівнює нулю. Залишається перевірити, до чого надсилаються тензорні добутки різних базових елементів. Індекси векторів тензорного добутку утворюють біекцію, тобто перестановку, при якій парні перестановки надсилаються до 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), тому перестановка є непарною.

Виправданням є те, що кожна транспозиція (заміна двох елементів) або додає одну інверсію, або забирає одну інверсію, поміняючи парність кількості інверсій, а паритет перестановки - це парність кількості транспозицій, необхідних для досягнення перестановки.

Тому, на закінчення, наша формула задана:

Чому це працює - нематеріальна версія

де σ є перестановкою 𝕊 п групи всіх перестановок п букв і SGN є знаком перестановки, AKA (-1) , зведена парності перестановки, і IJ є ( IJ ) записом в матриця ( i вниз, j поперек).


17
Та "нематеріальна версія" є досить чортова математика.
MD XF

6
Формули та символи та числа @MDXF навряд чи є математикою. Математика - це абстрагування та узагальнення та логіка, що лежить в основі формальних маніпуляцій символами.
Leaky Nun

7
@JAB Jelly реалізує власну власну кодову сторінку . (Днями TIO включить посилання на кодову сторінку ...)
повністюлюдсько

1
@Mego "продукти діагоналі суми" працюють лише для матриць 1x1, 2x2 та 3x3. Для більшої матриці потрібно враховувати всі перестановки та їх паритет.
Leaky Nun

3
+1 для насправді включте доказ у допис замість того, щоб сказати "оскільки ця формула вказана на сторінці abcxyz, вона повинна бути правдою".
користувач202729

11

R , 3 байти

Тривіальне рішення

det

Спробуйте в Інтернеті!

R , 94 92 байт

повторно реалізоване рішення

перевершив Ярко Дуббелдам

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

Використовує розширення Лапласа . Дякуємо @miles за те, що ти граєш 3 5 байт!

Спробуйте в Інтернеті!

Як це працює

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

Мова Вольфрама (Mathematica) , між 14 і 42 байтами

У нас було 3-байтне вбудоване та 53-байтове рішення, яке повністю уникає вбудованих модулів, тому ось дещо проміжні рішення десь посеред.

Мова Вольфрама має безліч дуже інтенсивних функцій для розкладання матриць на продукти інших матриць з більш простою структурою. Один з найпростіших (мається на увазі, я чув про це раніше) - розкладання Йорданії. Кожна матриця схожа на (можливо, складнозначну) верхню трикутну матрицю, виконану з діагональних блоків зі специфічною структурою, що називається Йорданським розкладанням цієї матриці. Подібність зберігає детермінанти, а визначником трикутної матриці є добуток діагональних елементів, тому ми можемо обчислити визначник із наступними 42 байтами :

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

Детермінанта також дорівнює добутку власних значень матриці з кратністю. На щастя, функція власного значення Вольфрама відслідковує кратність (навіть для недіагоналізуючих матриць), тому ми отримуємо наступне 20-байтне рішення:

1##&@@Eigenvalues@#&

Наступне рішення - це такий вид обману, і я не дуже впевнений, чому це працює. Вронський з списку n функцій є визначальним фактором матриці перших n -1 похідних функцій. Якщо ми дамо Wronskianфункції матрицю цілих чисел і скажемо, що змінна диференціації дорівнює 1, якимось чином випльовує визначник матриці. Це дивно, але це не включає букви " Det", і це лише 14 байт ...

#~Wronskian~1&

(The Casoratian детермінанта працює так само, для більш 1 байт: #~Casoratian~1&)

У царині абстрактної алгебри визначником матриці n  x  n (вважається картою k → k, що є множенням на визначник) є n- я зовнішня сила матриці (після вибору ізоморфізму k → ⋀ n k п ). У мові 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 деякий час тому. Вас це також може зацікавити. Яка чудова відповідь!
Mego

8

Haskell , 71 байт

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

Для цього використовується узгодження шаблону Хаскелла для розбиття матриці на голову (перший ряд) і хвіст (решту матриці).

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

Перерахуйте голову матриці (прокручуючи нескінченний список цілих чисел та голову) та повторіть її.

           (-1)*i*v

Негатуйте результат, ґрунтуючись на тому, чи є його індекс, оскільки обчислення визначника передбачає чергування додавання та віднімання.

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

Це по суті видаляє i-й стовпчик хвоста, беручи елементи i і з'єднуючи його з рядом з першими (i + 1) -ми елементами, скинутими для кожного ряду в хвості.

                   *f

Обчисліть визначник результату вище та помножте його на результат (-1)*i*v.

       sum

Підсумуйте результат списку вище та поверніть його.


2
ви можете зекономити 1 байт, замінивши його sum[(-1)^i*...наfoldr(-)0[...
Craig Roy

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)

Спробуйте в Інтернеті!

-3 байти завдяки містеру Xcoder
-3 байти завдяки Еріку Переверхувача

Розширення над першим рядом


Просто тому, що Протон не має вбудованого для визначального.
користувач202729

103 байт . ((~i%2)*2-1)->((-i%2)|1)
Містер Xcoder

Також 102 байти, замінивши j!=iна j-iабо i-j.
Містер Xcoder


@EriktheOutgolfer Ах так, дякую!
HyperNeutrino

5

Октава , 28 байт

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

Спробуйте в Інтернеті!

При цьому використовується QR - розкладання матричного X в orthgonal матриці Q і верхня трикутна матриця R . Визначник X є твором тих з Q і R . Ортогональна матриця має одиничний детермінант, а для трикутної матриці визначник є добутком її діагональних записів. Октава qrфункція викликається з одним виходом дає R .

Результат округляється до найближчого цілого числа. Для великих вхідних матриць неточності з плаваючою комою можуть спричинити помилку, що перевищує 0.5і, таким чином, призвести до неправильного результату.


1
Це цікавий спосіб уникнути detвбудованого. ;)
Томмед

1
@tomsmeding :-) Крім того, він уже був використаний у відповіді
Стюі


5

C,  176  125 байт

Дякуємо @ceilingcat за гольф 42 байти, а також @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)зберігає ще один байт.
Лінн

n+1+cможе бути n-~c.
Джонатан Фрех

Запропонувати i=sзамістьreturn s
roofcat

5

Желе , 43 байти

Нарешті я написав своє не вбудоване рішення гольф-мовою!

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

Дякуємо HyperNeutrino за збереження байта!

Спробуйте в Інтернеті! (пробіл для чіткості)

жахливо довгий шлях до видалення n'th елементів зі списку, покращиться згодом


Ця відповідь перевершила відповіді 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

-2 байти завдяки рішенню user202729


4

MATL , 3 байти / 5 байт

З вбудованою функцією

&0|

Спробуйте в Інтернеті!

Без вбудованого

Дякую Міші Лаврову за вказівку на помилку, тепер виправлену

YvpYo

Спробуйте в Інтернеті!

Це обчислює визначник як добуток власних значень, округлий до найближчого цілого числа, щоб уникнути неточностей з плаваючою комою.

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

Чи не добуток сингулярних значень вказує лише на абсолютне значення детермінанта?
Міша Лавров

@MishaLavrov Ви абсолютно праві! Дякуємо, що помітили. Я виправив це за допомогою власних значень замість сингулярних значень ... і це врятувало 4 байти \ о /
Луїс Мендо



3

TI-Basic, 2 байти

det(Ans

Ах, добре.

Будь ласка, не підтримуйте тривіальних відповідей.

Як студент середньої школи (який змушений володіти одним із цих калькуляторів), ця функція корисна, так що ...


8
Це все ще корисно в коледжі - лінійна алгебра не йде
Тейлор Скотт

5
@TaylorScott Насправді це повертається з помстою в диференціальних рівняннях.
Mego

@Mego - ти прав на це; хоча чомусь вони дозволили мені взяти все вичислення і це перед лінійним: /
Тейлор Скотт

1
@TaylorScott Через нагляд з математичного відділу мого університету, linalg не був необхідною умовою для різниці, коли я брав його. Коли мій професор зрозумів це, він швидко дав нам триденний курс краху в ліналі.
Mego

3

Хаскелл, 62 байти

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

Спробуйте в Інтернеті! (Нижній колонтитул із тестовими кейсами, взятіми з рішення @ totalhuman.)

dобчислює визначник, використовуючи розширення Лапласа уздовж першого стовпця. Потрібно на три байти більше, ніж постійний .


3

Python 2 , 95 байт

-12 байт завдяки Лінні.

Порт моєї відповіді Хаскелл .

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

Спробуйте в Інтернеті!


1
Тут також можна використовувати []як базовий корпус: f=lambda m:sum((-1)**i*v*f([j[:i]+j[i+1:]for j in m[1:]])for i,v in enumerate(m[0]))if m else 1на 95 байт!
Лінн

m==[]or sum(...)дає 92 байти.
Бубон

3

Мова Вольфрама (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}сказати, який запис у кожному рядку ми вибрали для відповідного продукту.

Ми застосовуємось 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якщо вони рівні.


-1 байт завдяки @ user202729


1
52 байти (якщо ви не знали цього
підказок щодо

Я так і зробив, але якось забув про це тут. Спасибі!
Міша Лавров

3

Python 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 масив на стеку і залишає ціле число на стеку.

Інтернет-тестовий набір

Розсічення

Це реалізує алгоритм Фаддєєва-Левер'є , і я думаю, що це перша відповідь, що застосовує такий підхід.

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 , різні

Ось безліч методів обчислення визначника, які мені здаються цікавими, усі вони запрограмовані в SageMath. Їх усіх можна спробувати тут .

Вбудований, 3 байти

det

Цей не надто цікавий. Мудрець надає псевдоніми глобального рівня для багатьох загальних операцій, які зазвичай є об'єктними методами, тому це коротше, ніж 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()))

У нормальній формі Йорданії матриця NxN представлена ​​у вигляді блокової матриці з N блоками по діагоналі. Кожен блок складається або з одного власного значення, або з матриці MxM з повторним власним значенням по діагоналі і 1s на наддіагоналі (діагональ вище і праворуч від "основної" діагоналі). Це призводить до отримання матриці з усіма власними значеннями (з кратністю) на головній діагоналі, а деякі 1s на наддіагоналі, що відповідає повторним власним значенням. Це повертає добуток діагоналі Йордану нормальної форми, що є добутком власних значень (з кратністю), тому це більш крутий спосіб виконання тих же обчислень, що і попереднє рішення.

Оскільки Сейдж хоче, щоб нормальна форма Йордану була над тим же кільцем, що і вихідна матриця, це працює лише в тому випадку, якщо всі власні значення є раціональними. Складні власні значення призводять до помилки (якщо тільки первісна матриця не над кільцем CDF(складні подвійні поплавці) або SR). Однак це означає, що брати реальну участь не потрібно, порівняно з вищезазначеним рішенням.


Продукт Діагоналі в розкладанні Сміта

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

На відміну від нормальної форми Йорданії, нормальна форма Сміта гарантовано знаходиться над тим же полем, що і вихідна матриця. Замість того, щоб обчислювати власні значення та представляти їх за допомогою блок-діагональної матриці, Ском Сміт обчислює елементарні дільники матриці (що є надто складною для цього поста), ставить їх у діагональну матрицю Dта обчислює дві матриці з одиницею визначальний Uі Vтакий, що D = U*A*V(де Aоригінальна матриця). Так як визначник твори матриць дорівнює добутку визначників матриць ( 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власних значень s. Для дійсних чисел r_1і r_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

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 байти з такою ж поведінкою
Арнольд

Або 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;
}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.