Codegolf o permanente

20

O desafio é escrever codegolf para a permanente de uma matriz .

A permanente de uma matriz- nby = ( ) é definida comonAai,j

insira a descrição da imagem aqui

Aqui S_nrepresenta o conjunto de todas as permutações de [1, n].

Como um exemplo (do wiki):

insira a descrição da imagem aqui

Seu código pode receber entrada da maneira que desejar e fornecer saída em qualquer formato razoável, mas inclua na sua resposta um exemplo completo, incluindo instruções claras de como fornecer entrada para o seu código. Para tornar o desafio um pouco mais interessante, a matriz pode incluir números complexos.

A matriz de entrada é sempre quadrada e terá no máximo 6 por 6. Você também precisará lidar com a matriz vazia que possui o 1. permanente. Não há necessidade de lidar com a matriz vazia (isso estava causando muitos problemas).

Exemplos

Entrada:

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

Resultado:

-1.7421952844303492+2.2476833142265793j

Entrada:

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

Resultado:

-1.972117936608412+1.6081325306004794j

Entrada:

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

Resultado:

-22.92354821347135-90.74278997288275j

Você não pode usar nenhuma função pré-existente para calcular a permanente.


fonte
12
Você poderia remover o requisito complexo? Eu acho que isso arruina um desafio agradável. Todo idioma que não possui aritmética complexa incorporada agora precisa executar uma tarefa totalmente separada.
Xnor
6
Se precisarmos lidar com a matriz vazia, você deve adicioná-la como um caso de teste. O fato de você não poder realmente representar a matriz 0x0 com listas torna isso um pouco difícil. Pessoalmente, eu apenas removeria esse requisito.
Dennis
4
Não faz sentido colocar algo na caixa de areia por 3 horas. Dê três dias e as pessoas terão a chance de dar um feedback.
Peter Taylor
7
1. Não são apenas esolangs. Bash, por exemplo, não consegue nem lidar nativamente com carros alegóricos . Excluir um idioma da competição apenas porque não possui um determinado tipo numérico, mesmo que possa implementar sem esforço o algoritmo desejado, está apenas sendo exigente sem um bom motivo. 2. Ainda não tenho certeza sobre a matriz vazia. Seria [[]](possui uma linha, a matriz vazia não) ou [](não possui profundidade 2, matrizes possuem) em forma de lista?
Dennis
4
1. Não estou pensando que seja impossível resolver esse desafio no Bash, mas se a maior parte do código for usada para lidar com aritmética complexa de números, ele deixará de ser um desafio sobre permanentes. 2. A maioria, se não todas, as respostas atuais são idiomas sem uma quebra de tipo de matriz para entrada [[]].
Dennis

Respostas:

11

J, 5 bytes

+/ .*

J não oferece embutidos para o permanente ou determinante, mas oferece uma conjunção u . v yque se expande recursivamente yao longo dos menores e calcula diádica u . ventre os cofatores e a saída da chamada recursiva aos menores. As opções ue vpodem variar. Por exemplo, usando u =: -/e v =: *é -/ .*qual é o determinante. As escolhas podem, mesmo por %/ .!onde u=: %/, reduzir por divisão e v =: !qual é o coeficiente binomial. Não sei ao certo o que essa saída significa, mas você pode escolher seus verbos.

Uma implementação alternativa para 47 bytes usando o mesmo método na minha resposta do Mathematica .

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

Isso simula um polinômio com n variáveis, criando um polinômio com uma variável aumentada para potências de 2. Isso é mantido como uma lista de coeficientes e a multiplicação polinomial é realizada por convolução, e o índice em 2 n conterá o resultado.

Outra implementação para 31 bytes é

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

que é uma versão ligeiramente golfe, com base na expansão de Laplace, extraída do ensaio J sobre determinantes .

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
milhas
fonte
11
Uau é tudo o que posso dizer.
13

Haskell, 59 bytes

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

Isso faz um desenvolvimento semelhante ao Laplace ao longo da primeira coluna e usa que a ordem das linhas não importa. Funciona para qualquer tipo numérico.

A entrada é como lista de listas:

Prelude> p [[1,2],[3,4]]
10
Peneiradores cristãos
fonte
2
Sempre receba uma solução Haskell!
8

Geléia , 10 9 bytes

Œ!ŒDḢ€P€S

Experimente online!

Como funciona

Œ!Œ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
fonte
É bom demais!
7

Python 2, 75 bytes

Parece desajeitado ... deve ser superável.

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
fonte
6

05AB1E , 19 14 13 bytes

œvyvyNè}Pˆ}¯O

Experimente online!

Explicação

œ              # 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
fonte
Uma resposta um pouco chocante! Você poderia dar uma explicação?
@Lembik: Parece que poderia ser mais curto ainda. Eu tenho uma segunda solução do mesmo tamanho até agora.
Emigna
O tratamento de matrizes vazias não é mais necessário.
Dennis
8 bytes usando mapas . Pena que o novo 05AB1E não suporta números imaginários (ou eu simplesmente não sei como), uma vez que agora temos uma principal builtin diagonal e isso poderia ter sido 6 bytes: œ€Å\PO.
Kevin Cruijssen 6/12
5

Python 2, 139 bytes

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 o algoritmo ingênuo que segue cegamente a definição.

Jonathan Allan
fonte
4

MATL, 17 14 bytes

tZyt:tY@X])!ps

Experimente Online

Explicação

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
fonte
11
Muito impressionante.
4

Rubi, 74 63 bytes

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

Uma tradução direta da fórmula. Vários bytes salvos graças ao ezrast.

Explicação

->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
fonte
11
reducerealmente prejudica sua contagem de bytes em comparação à agregação manual:->a{m=0;a.permutation{|b|n=1;a.size.times{|i|n*=b[i][i]};m+=n};m}
ezrast 21/10
@ezrast Obrigado! Conseguiu jogar golfe nesse timescircuito também.
precisa saber é o seguinte
3

Ruby 2.4.0, 59 61 bytes

Expansão recursiva de Laplace:

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

Menos golfe:

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
}

O Ruby 2.4 não é lançado oficialmente. Nas versões anteriores, .sumserá necessário substituir por .reduce(:+), adicionando 7 bytes.

ezrast
fonte
2

Mathematica, 54 bytes

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

Agora que as matrizes vazias não são mais consideradas, esta solução é válida. É originário da página MathWorld em permanentes .

milhas
fonte
@alephalpha Essa é uma idéia interessante de usar as linhas para identificar coeficientes, mas não seria quebrado se as linhas não fossem únicas?
miles
2

JavaScript (ES6), 82 bytes

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

Também funciona com a matriz vazia, é claro.

Neil
fonte
@ETHproductions Eu nunca aprendo ...
Neil
11
Exatamente o meu código, publicado apenas 14 horas antes, eu vou tentar adicionar números complexos
edc65
2

Julia 0.4 , 73 bytes

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

Nas versões mais recentes do julia, você pode ignorar []as compreensões, mas precisa using Combinatoricsda permutationsfunção. Funciona com todos os tipos de números em Julia, incluindoComplex . ré um UnitRangeobjeto definido como um argumento de função padrão, que pode depender de argumentos de função anteriores.

Experimente online!

gggg
fonte