Codegolf permanent

20

Wyzwanie polega na napisaniu codegolfa na stałe matrycy .

Stała n-by- nmatrix A= ( ai,j) jest zdefiniowana jako

wprowadź opis zdjęcia tutaj

Tutaj S_nreprezentuje zestaw wszystkich permutacji [1, n].

Jako przykład (z wiki):

wprowadź opis zdjęcia tutaj

Kod może przyjmować dane wejściowe w dowolny sposób i dawać dane wyjściowe w dowolnym rozsądnym formacie, ale w odpowiedzi należy podać pełny sprawdzony przykład, w tym jasne instrukcje dotyczące sposobu wprowadzania danych wejściowych do kodu. Aby wyzwanie było trochę bardziej interesujące, macierz może zawierać liczby zespolone.

Matryca wejściowa jest zawsze kwadratowa i będzie wynosić co najwyżej 6 na 6. Będziesz także musiał obsługiwać pustą macierz, która ma stałą 1. Nie ma potrzeby obsługi pustej macierzy (powodowało to zbyt wiele problemy).

Przykłady

Wejście:

[[ 0.36697048+0.02459455j,  0.81148991+0.75269667j,  0.62568185+0.95950937j],
 [ 0.67985923+0.11419187j,  0.50131790+0.13067928j,  0.10330161+0.83532727j],
 [ 0.71085747+0.86199765j,  0.68902048+0.50886302j,  0.52729463+0.5974208j ]]

Wynik:

-1.7421952844303492+2.2476833142265793j

Wejście:

[[ 0.83702504+0.05801749j,  0.03912260+0.25027115j,  0.95507961+0.59109069j],
 [ 0.07330546+0.8569899j ,  0.47845015+0.45077079j,  0.80317410+0.5820795j ],
 [ 0.38306447+0.76444045j,  0.54067092+0.90206306j,  0.40001631+0.43832931j]]

Wynik:

-1.972117936608412+1.6081325306004794j

Wejście:

 [[ 0.61164611+0.42958732j,  0.69306292+0.94856925j,
     0.43860930+0.04104116j,  0.92232338+0.32857505j,
     0.40964318+0.59225476j,  0.69109847+0.32620144j],
   [ 0.57851263+0.69458731j,  0.21746623+0.38778693j,
     0.83334638+0.25805241j,  0.64855830+0.36137045j,
     0.65890840+0.06557287j,  0.25411493+0.37812483j],
   [ 0.11114704+0.44631335j,  0.32068031+0.52023283j,
     0.43360984+0.87037973j,  0.42752697+0.75343656j,
     0.23848512+0.96334466j,  0.28165516+0.13257001j],
   [ 0.66386467+0.21002292j,  0.11781236+0.00967473j,
     0.75491373+0.44880959j,  0.66749636+0.90076845j,
     0.00939420+0.06484633j,  0.21316223+0.4538433j ],
   [ 0.40175631+0.89340763j,  0.26849809+0.82500173j,
     0.84124107+0.23030393j,  0.62689175+0.61870543j,
     0.92430209+0.11914288j,  0.90655023+0.63096257j],
   [ 0.85830178+0.16441943j,  0.91144755+0.49943801j,
     0.51010550+0.60590678j,  0.51439995+0.37354955j,
     0.79986742+0.87723514j,  0.43231194+0.54571625j]]

Wynik:

-22.92354821347135-90.74278997288275j

Nie można używać żadnych wcześniej istniejących funkcji do obliczania wartości stałej.


źródło
12
Czy możesz usunąć złożone wymaganie? Myślę, że rujnuje to całkiem miłe wyzwanie. Każdy język, który nie ma wbudowanej złożonej arytmetyki, musi teraz wykonywać zupełnie inne zadanie.
xnor
6
Jeśli musimy obsłużyć pustą macierz, powinieneś dodać ją jako przypadek testowy. Fakt, że tak naprawdę nie możesz reprezentować macierzy 0x0 z listami, sprawia, że ​​jest to trochę trudne. Osobiście po prostu usunę ten wymóg.
Dennis,
4
Nie ma sensu wkładać czegoś do piaskownicy na 3 godziny. Daj mu 3 dni, a ludzie będą mieli okazję wyrazić opinię.
Peter Taylor,
7
1. To nie tylko esolangi. Bash, na przykład, nie może nawet natywnie poradzić sobie z pływakami . Wykluczenie języka z konkursu tylko dlatego, że brakuje mu określonego typu liczbowego, nawet jeśli można bez trudu zaimplementować pożądany algorytm, jest po prostu wybredny bez powodu. 2. Nadal nie jestem pewien co do pustej matrycy. Czy byłby [[]](ma jeden wiersz, pusta matryca nie) lub [](nie ma głębokości 2, matryce mają) w formie listy?
Dennis,
4
1. Nie zastanawiam się, czy nie można rozwiązać tego wyzwania w Bash, ale jeśli lwia część kodu jest używana do radzenia sobie z arytmetyką liczb zespolonych, przestaje być wyzwaniem dotyczącym stałych. 2. Większość, jeśli nie wszystkie aktualne odpowiedzi, to języki bez podziału typu macierzy na dane wejściowe [[]].
Dennis,

Odpowiedzi:

11

J, 5 bajtów

+/ .*

J nie oferuje wbudowanych stałych lub determinant, ale zamiast tego oferuje koniunkcję, u . v yktóra rekurencyjnie rozwija się ywzdłuż nieletnich i oblicza różnicę u . vmiędzy kofaktorami a wydajnością wywołania rekurencyjnego na nieletnich. Wybory ui vmogą się różnić. Na przykład użycie u =: -/i v =: *jest -/ .*wyznacznikiem. Wybory mogą nawet według %/ .!miejsca u=: %/, zmniejszyć przez podział i v =: !który jest współczynnikiem dwumianowym. Nie jestem pewien, co oznacza to wyjście, ale możesz swobodnie wybierać czasowniki.

Alternatywna implementacja dla 47 bajtów przy użyciu tej samej metody w mojej odpowiedzi Mathematica .

_1{[:($@]$[:+//.*/)/0,.;@(<@(,0#~<:)"+2^i.@#)"{

Symuluje to wielomian ze zmiennymi n , tworząc wielomian z jedną zmienną podniesioną do potęg 2. To jest utrzymywane jako lista współczynników, a mnożenie wielomianowe jest wykonywane przy użyciu splotu, a indeks przy 2 n będzie zawierał wynik.

Inną implementacją dla 31 bajtów jest

+/@({.*1$:\.|:@}.)`(0{,)@.(1=#)

która jest lekko golfową wersją opartą na rozszerzeniu Laplace'a zaczerpniętym z eseju J na temat wyznaczników .

Stosowanie

   f =: +/ .*
   f 0 0 $ 0 NB. the empty matrix, create a shape with dimensions 0 x 0
1
   f 0.36697048j0.02459455 0.81148991j0.75269667 0.62568185j0.95950937 , 0.67985923j0.11419187  0.50131790j0.13067928 0.10330161j0.83532727 ,: 0.71085747j0.86199765 0.68902048j0.50886302 0.52729463j0.5974208
_1.7422j2.24768
   f 0.83702504j0.05801749 0.03912260j0.25027115 0.95507961j0.59109069 , 0.07330546j0.8569899 0.47845015j0.45077079 0.80317410j0.5820795 ,: 0.38306447j0.76444045 0.54067092j0.90206306 0.40001631j0.43832931
_1.97212j1.60813
   f 0.61164611j0.42958732 0.69306292j0.94856925 0.4386093j0.04104116 0.92232338j0.32857505 0.40964318j0.59225476 0.69109847j0.32620144 , 0.57851263j0.69458731 0.21746623j0.38778693 0.83334638j0.25805241 0.6485583j0.36137045 0.6589084j0.06557287 0.25411493j0.37812483 , 0.11114704j0.44631335 0.32068031j0.52023283 0.43360984j0.87037973 0.42752697j0.75343656 0.23848512j0.96334466 0.28165516j0.13257001 , 0.66386467j0.21002292 0.11781236j0.00967473 0.75491373j0.44880959 0.66749636j0.90076845 0.0093942j0.06484633 0.21316223j0.4538433 , 0.40175631j0.89340763 0.26849809j0.82500173 0.84124107j0.23030393 0.62689175j0.61870543 0.92430209j0.11914288 0.90655023j0.63096257 ,: 0.85830178j0.16441943 0.91144755j0.49943801 0.5101055j0.60590678 0.51439995j0.37354955 0.79986742j0.87723514 0.43231194j0.54571625
_22.9235j_90.7428
mile
źródło
1
Wow to wszystko co mogę powiedzieć.
13

Haskell, 59 bajtów

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

Robi to podobnie jak Laplace'a wzdłuż pierwszej kolumny i używa, że ​​kolejność wierszy nie ma znaczenia. Działa dla każdego typu liczbowego.

Dane wejściowe są jak lista list:

Prelude> p [[1,2],[3,4]]
10
Christian Sievers
źródło
2
Zawsze witaj rozwiązanie Haskell!
8

Galaretka , 10 9 bajtów

Œ!ŒDḢ€P€S

Wypróbuj online!

Jak to działa

Œ!ŒDḢ€P€S  Main link. Argument: M (matrix / 2D array)

Œ!         Generate all permutations of M's rows.
  ŒD       Compute the permutations' diagonals, starting with the main diagonal.
    Ḣ€     Head each; extract the main diagonal of each permutation.
      P€   Product each; compute the products of the main diagonals.
        S  Compute the sum of the products.
Dennis
źródło
To jest po prostu zbyt dobre!
7

Python 2, 75 bajtów

Wydaje się niezgrabny ... powinien być dający się pokonać.

P=lambda m,i=0:sum([r[i]*P(m[:j]+m[j+1:],i+1)for j,r in enumerate(m)]or[1])
feersum
źródło
6

05AB1E , 19 14 13 bajtów

œvyvyNè}Pˆ}¯O

Wypróbuj online!

Wyjaśnienie

œ              # get all permutations of rows
 v        }    # for each permutation
  yv   }       # for each row in the permutation
    yNè        # get the element at index row-index
        P      # product of elements
         ˆ     # add product to global array
           ¯O  # sum the products from the global array
Emigna
źródło
Nieco szokująca odpowiedź! Czy możesz podać jakieś wyjaśnienie?
@Lembik: Wydaje się, że może być jeszcze krótszy. Do tej pory mam drugie rozwiązanie tego samego rozmiaru.
Emigna,
Obsługa pustych macierzy nie jest już wymagana.
Dennis,
8 bajtów przy użyciu map . Szkoda tylko, że nowy 05AB1E nie obsługuje liczb urojonych (lub po prostu nie wiem jak), ponieważ teraz mamy głównej przekątnej polecenie wbudowane i to mogło być 6 bajtów: œ€Å\PO.
Kevin Cruijssen
5

Python 2, 139 bajtów

from itertools import*
def p(a):c=complex;r=range(len(a));return sum(reduce(c.__mul__,[a[j][p[j]]for j in r],c(1))for p in permutations(r))

repl.it

Implementuje naiwny algorytm, który ślepo podąża za definicją.

Jonathan Allan
źródło
4

MATL, 17 14 bajtów

tZyt:tY@X])!ps

Wypróbuj online

Wyjaśnienie

t       % Implicitly grab input and duplicate
Zy      % Compute the size of the input. Yields [rows, columns]
t:      % Compute an array from [1...rows]
tY@     % Duplicate this array and compute all permutations (these are the columns)
X]      % Convert row/column to linear indices into the input matrix
)       % Index into the input matrix where each combination is a row
!p      % Take the product of each row
s       % Sum the result and implicitly display
Suever
źródło
1
Bardzo imponujące.
4

Rubin, 74 63 bajty

->a{p=0;a.permutation{|b|n=1;i=-1;a.map{n*=b[i+=1][i]};p+=n};p}

Proste tłumaczenie formuły. Kilka bajtów zapisanych dzięki ezrast.

Wyjaśnienie

->a{
    # Initialize the permanent to 0
    p=0
    # For each permutation of a's rows...
    a.permutation{|b|
        # ... initialize the product to 1,
        n=1
        # initialize the index to -1; we'll use this to go down the main diagonal
        # (i starts at -1 because at each step, the first thing we do is increment i),
        i=-1
        # iteratively calculate the product,
        a.map{
            n*=b[i+=1][i]
        }
        # increase p by the main diagonal's product.
        p+=n
    }
    p
}
m-chrzan
źródło
1
reducefaktycznie boli liczbę bajtów w porównaniu do ręcznego agregowania:->a{m=0;a.permutation{|b|n=1;a.size.times{|i|n*=b[i][i]};m+=n};m}
ezrast
@ezrast Dzięki! Udało mu się także zagrać w golfa w tej timespętli.
m-chrzan
3

Ruby 2.4.0, 59 61 bajtów

Rekurencyjne rozszerzenie Laplace'a:

f=->a{a.pop&.map{|n|n*f[a.map{|r|r.rotate![0..-2]}]}&.sum||1}

Mniej golfa:

f=->a{
  # Pop a row off of a
  a.pop&.map{ |n|
    # For each element of that row, multiply by the permanent of the minor
    n * f[a.map{ |r| r.rotate![0..-2]}]
  # Add all the results together
  }&.sum ||
  # Short circuit to 1 if we got passed an empty matrix
  1
}

Ruby 2.4 nie jest oficjalnie wydany. We wcześniejszych wersjach .sumnależy go zastąpić .reduce(:+), dodając 7 bajtów.

ezrast
źródło
2

Mathematica, 54 bajty

Coefficient[Times@@(#.(v=x~Array~Length@#)),Times@@v]&

Teraz, gdy puste matryce nie są już brane pod uwagę, to rozwiązanie jest poprawne. Pochodzi ze strony MathWorld na stałe .

mile
źródło
@alephalpha To fajny pomysł, aby użyć wierszy do zidentyfikowania współczynników, ale czy nie złamałby się, gdyby wiersze nie były unikalne?
mil
2

JavaScript (ES6), 82 bajty

f=a=>a[0]?a.reduce((t,b,i)=>t+b[0]*f(a.filter((_,j)=>i-j).map(c=>c.slice(1))),0):1

Oczywiście działa również z pustą matrycą.

Neil
źródło
@ETHproductions Nigdy się nie uczę ...
Neil
1
Dokładnie mój kod, właśnie opublikowany 14 godzin wcześniej, postaram się dodać liczby zespolone
edc65
2

Julia 0.4 , 73 bajty

f(a,r=1:size(a,1))=sum([prod([a[i,p[i]] for i=r]) for p=permutations(r)])

W nowszych wersjach Julii możesz porzucić []rozeznanie, ale potrzebujeszusing Combinatorics do permutationsfunkcji. Działa ze wszystkimi typami liczb w Julii, w tym Complex. rto UnitRangeobiekt zdefiniowany jako domyślny argument funkcji, który może zależeć od poprzednich argumentów funkcji.

Wypróbuj online!

gggg
źródło