Codegolf il permanente


20

La sfida è scrivere codegolf per il permanente di una matrice .

Il permanente di una n-by- nmatrix A= ( ai,j) è definito come

inserisci qui la descrizione dell'immagine

Qui S_nrappresenta l'insieme di tutte le permutazioni di [1, n].

Ad esempio (dal wiki):

inserisci qui la descrizione dell'immagine

Il tuo codice può ricevere input nel modo desiderato e fornire output in qualsiasi formato ragionevole, ma includi nella tua risposta un esempio completo che includa chiare istruzioni su come fornire input al tuo codice. Per rendere la sfida un po 'più interessante, la matrice può includere numeri complessi.

La matrice di input è sempre quadrata e sarà al massimo di 6 per 6. Dovrai anche essere in grado di gestire la matrice vuota che ha permanente 1. Non è necessario essere in grado di gestire la matrice vuota (ne causava troppe i problemi).

Esempi

Ingresso:

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

Produzione:

-1.7421952844303492+2.2476833142265793j

Ingresso:

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

Produzione:

-1.972117936608412+1.6081325306004794j

Ingresso:

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

Produzione:

-22.92354821347135-90.74278997288275j

Non è possibile utilizzare alcuna funzione preesistente per calcolare il permanente.


12
Potresti rimuovere il requisito complesso? Penso che rovini una sfida altrimenti piacevole. Ogni lingua che non ha un'aritmetica complessa integrata ora deve svolgere un compito completamente separato.
xnor

6
Se dobbiamo gestire la matrice vuota, è necessario aggiungerla come caso di test. Il fatto che non sia possibile rappresentare realmente la matrice 0x0 con le liste rende questo un po 'difficile. Personalmente, rimuoverei questo requisito.
Dennis,

4
Non ha senso mettere qualcosa nella sandbox per 3 ore. Dagli 3 giorni e le persone hanno la possibilità di dare un feedback.
Peter Taylor,

7
1. Non sono solo esolang. Bash, ad esempio, non può nemmeno gestire nativamente i float . Escludere un linguaggio dalla concorrenza solo perché manca di un certo tipo numerico, anche se può implementare senza sforzo l'algoritmo desiderato, è solo pignolo per nessun motivo. 2. Non sono ancora sicuro della matrice vuota. Sarebbe [[]](ha una riga, la matrice vuota no) o [](non ha profondità 2, le matrici lo fanno) in forma di elenco?
Dennis,

4
1. Non sto pensando che sia impossibile risolvere questa sfida in Bash, ma se la parte leone del codice viene utilizzata per gestire l'aritmetica dei numeri complessi, smette di essere una sfida per i permanenti. 2. La maggior parte se non tutte le risposte correnti sono le lingue senza un'interruzione del tipo di matrice per l'input [[]].
Dennis,

Risposte:


11

J, 5 byte

+/ .*

J non offre builtin per il permanente o determinante ma offre invece una congiunzione u . v yche si espande in modo ricorsivo ylungo i minori e calcola la diade u . vtra i cofattori e l'output della chiamata ricorsiva sui minori. Le scelte di ue vpossono variare. Ad esempio, utilizzando u =: -/ed v =: *è -/ .*che è il determinante. Le scelte possono anche da %/ .!dove u=: %/, ridurre per divisione e v =: !quale è il coefficiente binomiale. Non sono sicuro di cosa significhi quell'output ma sei libero di scegliere i tuoi verbi.

Un'implementazione alternativa per 47 byte usando lo stesso metodo nella mia risposta Mathematica .

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

Questo simula un polinomio con n variabili creando un polinomio con una variabile elevata a potenze di 2. Questo è tenuto come un elenco di coefficienti e la moltiplicazione polinomiale viene eseguita usando la convoluzione e l'indice a 2 n conterrà il risultato.

Un'altra implementazione per 31 byte è

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

che è una versione leggermente golfata basata sull'espansione di Laplace tratta dal saggio J sui determinanti .

uso

   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

1
Wow è tutto ciò che posso dire.

13

Haskell, 59 byte

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

Questo fa uno sviluppo simile a Laplace lungo la prima colonna e usa che l'ordine delle righe non ha importanza. Funziona con qualsiasi tipo numerico.

L'input è come elenco di elenchi:

Prelude> p [[1,2],[3,4]]
10

2
Accogli sempre con favore una soluzione Haskell!

8

Gelatina , 10 9 byte

Œ!ŒDḢ€P€S

Provalo online!

Come funziona

Œ!Œ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.

È semplicemente troppo bello!

7

Python 2, 75 byte

Sembra ingombrante ... dovrebbe essere battibile.

P=lambda m,i=0:sum([r[i]*P(m[:j]+m[j+1:],i+1)for j,r in enumerate(m)]or[1])

6

05AB1E , 19 14 13 byte

œvyvyNè}Pˆ}¯O

Provalo online!

Spiegazione

œ              # 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

Una risposta leggermente scioccante! Potresti fornire qualche spiegazione?

@Lembik: sembra che potrebbe essere ancora più breve. Finora ho una seconda soluzione della stessa dimensione.
Emigna,

Non è più necessario gestire matrici vuote.
Dennis,

8 byte utilizzando le mappe . Peccato che il nuovo 05AB1E non supporta numeri immaginari (o semplicemente non so come), dal momento che ora abbiamo un principale incorporato diagonale e questo avrebbe potuto essere 6 byte: œ€Å\PO.
Kevin Cruijssen il

5

Python 2, 139 byte

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

Implementa l'algoritmo ingenuo che segue ciecamente la definizione.


4

MATL, 17 14 byte

tZyt:tY@X])!ps

Provalo online

Spiegazione

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

1
Molto impressionante.

4

Rubino, 74 63 byte

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

Una traduzione semplice della formula. Diversi byte salvati grazie a ezrast.

Spiegazione

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

1
reducein realtà fa male il conteggio dei byte rispetto all'aggregazione manuale:->a{m=0;a.permutation{|b|n=1;a.size.times{|i|n*=b[i][i]};m+=n};m}
ezrast

@ezrast Grazie! Gestito anche per giocare a golf times.
m-chrzan,

3

Ruby 2.4.0, 59 61 byte

Espansione ricorsiva di Laplace:

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

Meno golf:

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 non è ufficialmente rilasciato. Nelle versioni precedenti, .sumdovrà essere sostituito con l' .reduce(:+)aggiunta di 7 byte.


2

Mathematica, 54 byte

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

Ora che le matrici vuote non vengono più prese in considerazione, questa soluzione è valida. Proviene dalla pagina MathWorld sui permanenti .


@alephalpha È una buona idea usare le righe per identificare i coefficienti ma non si spezzerebbe se le righe non fossero uniche?
miglia

2

JavaScript (ES6), 82 byte

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

Funziona anche con la matrice vuota, ovviamente.


@ETHproductions Non imparo mai ...
Neil,

1
Esattamente il mio codice, appena pubblicato 14 ore prima, proverò ad aggiungere numeri complessi
edc65,

2

Julia 0.4 , 73 byte

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

Nelle versioni più recenti di julia è possibile ignorare []le comprensioni, ma è necessario using Combinatoricsper la permutationsfunzione. Funziona con tutti i tipi di numero in Julia, incluso Complex. rè un UnitRangeoggetto definito come argomento di funzione predefinito, che può dipendere da argomenti di funzioni precedenti.

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.