Vandermonde Determinant

25

Dado um vetor de nvalores, (x1,x2,x3,...,xn)retorne o determinante da matriz de Vandermonde correspondente .

Este determinante pode ser escrito como:

Fórmula

Detalhes

Seu programa / função precisa aceitar uma lista de números de ponto flutuante em qualquer formato conveniente que permita um comprimento variável e gerar o determinante especificado.

Você pode assumir que a entrada e a saída estão dentro do intervalo dos valores que seu idioma suporta. Se o seu idioma não suportar números de ponto flutuante, você poderá assumir números inteiros.

Alguns casos de teste

Observe que sempre que houver duas entradas iguais, o determinante será o de 0duas linhas iguais na matriz de Vandermonde correspondente. Agradecemos a @randomra por apontar esse caso de teste ausente.

[1,2,2,3]            0 
[-13513]             1
[1,2]                1
[2,1]               -1
[1,2,3]              2
[3,2,1]             -2
[1,2,3,4]           12
[1,2,3,4,5]        288
[1,2,4]              6
[1,2,4,8]         1008
[1,2,4,8,16]  20321280
[0, .1, .2,...,1]   6.6586e-028
[1, .5, .25, .125]  0.00384521
[.25, .5, 1, 2, 4]  19.3798828
flawr
fonte
Podemos supor que a entrada tenha pelo menos 2 de comprimento?
PurkkaKoodari
@ Pietu1998 Não, veja o primeiro caso de teste.
Alex A.
3
Caso de teste importante [1,2,2,3] => 0:: dois elementos iguais na matriz, para testar se o código verifica a auto-diferença ( xi-xi) apenas comparando com 0.
Aleatório
@ randomra Obrigado, eu esqueci totalmente de incluir um deles. Sempre que duas entradas são iguais, o determinante será 0, pois há duas vezes a mesma linha.
flawr
1
@flawr A saída esperada ficou clara com suas especificações. Sugeri o caso de teste para que respostas não preparadas para números iguais pudessem encontrar seus erros mais facilmente.
randomra

Respostas:

9

Gelatina, 6 bytes

œc2IFP

œc2obtém todas as combinações sem substituir o comprimento 2. Icalcula a lista de diferenças de cada um desses pares, produzindo uma lista como [[1], [2], [3], ..., [1]]. Nós FLatten e tomar o Produto.

Experimente aqui!

Lynn
fonte
8

Ruby, 49 47 bytes

->x{eval(x.combination(2).map{|a,b|b-a}*?*)||1}

Essa é uma função lambda que aceita uma matriz unidimensional com valor real e retorna um número flutuante ou um número inteiro, dependendo do tipo da entrada. Para chamá-lo, atribua-o a uma variável e faça f.call(input).

Obtemos todas as combinações de tamanho 2 usando .combination(2)e obtemos as diferenças para cada par usando .map {|a, b| b - a}. Juntamos a matriz resultante em uma sequência separada por *, então evalisto, que retorna o produto. Se a entrada tiver comprimento 1, será o nilque é falsey em Ruby, para que possamos ||1retornar no final 1 nessa situação. Observe que isso ainda funciona quando o produto é 0 porque, por qualquer motivo, 0 é verdadeiro no Ruby.

Verifique todos os casos de teste online

Economizou 2 bytes graças a Maçaneta!

Alex A.
fonte
7

Mathematica, 30 bytes

1##&@@(#2-#&@@@#~Subsets~{2})&

Esta é uma função anônima.

Expandido pelo Mathematica, é equivalente a (1 ##1 & ) @@ Apply[#2 - #1 & , Subsets[#1, {2}], {1}] &. 1##&é equivalente a Times(página de dicas de agradecimento), que é aplicada a cada par distinto de elementos da lista de entrada, gerado por Subsets[list, {2}]. Observe que Subsetsnão verifica a exclusividade dos elementos.

feersum
fonte
5

J, 13 bytes

-/ .*@(^/i.)#

Esta é uma função monádica que recebe uma matriz e retorna um número. Use-o assim:

  f =: -/ .*@(^/i.)#
  f 1 2 4
6

Explicação

Construo explicitamente a matriz de Vandermonde associada à matriz de entrada e depois calculo seu determinante.

-/ .*@(^/i.)#   Denote input by y
            #   Length of y, say n
         i.     Range from 0 to n - 1
       ^/       Direct product of y with the above range using ^ (power)
                This gives the Vandermonde matrix
                 1 y0     y0^2     ... y0^(n-1)
                 1 y1     y1^2     ... y1^(n-1)
                   ...
                 1 y(n-1) y(n-1)^2 ... y(n-1)^(n-1)
-/ .*           Evaluate the determinant of this matrix
Zgarb
fonte
Pensei espaço em branco foi não-crucial na J ...
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ O determinante é um caso especial que requer um espaço de separação, uma vez que .também é um carácter modificador. O mesmo por :si só.
Zgarb
Oh! Isso é legal.
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Na verdade, acho que é exatamente isso que faz J não ser legal. J significa Jot, ou seja, um ponto ou anelzinho (APL ), como anotando J ... O incrivelmente sobrecarregado .e :(que novamente é visualmente o mesmo que dois .s empilhados ) tornam J difícil de ler (para mim). Quanto mais quando o espaço em branco ao lado dos pontos determina o significado! J .deve ser o símbolo mais sobrecarregado de toda a história da computação: conto 53 significados distintos de .e 43 (61 se você contar todos ) _9:até 9:significados distintos de :. Yukk. ;-)
Adám 7/03/16
@ Nᴮᶻ pode ajudar a pensar no. como seu próprio símbolo; assim, poderia, sem um espaço em branco, ser confundido com outro operador. Se J não é para você, no entanto, isso é compreensível.
Conor O'Brien
4

MATL , 9

!G-qZRQpp

Experimente online!

Isso calcula uma matriz de todas as diferenças e mantém apenas a parte abaixo da diagonal principal, fazendo as outras entradas 1para que elas não afetem o produto. A função triangular inferior cria os elementos indesejados 0, não 1. Então subtraímos 1, pegamos a parte triangular inferior e adicionamos de 1volta. Então podemos pegar o produto de todas as entradas.

t     % take input. Transpose
G     % push input again
-     % subtract with broadccast: matrix of all pairwise differences
q     % subtract 1
ZR    % make zero all values on the diagonal and above
Q     % add 1
p     % product of all columns
p     % product of all those products
Luis Mendo
fonte
É lamentável, mas 2Xn!dpsó parece funcionar com valores individuais quando o valor for maior ou igual a 2 ... eu tinha escrito isso sozinho tentando bater Jelly: P
FryAmTheEggman
@FryAmTheEggman Awww. Você está certo. Obrigado pelo alerta!
Luis Mendo
Sim, achei que esse era o problema. Eu consideraria tentar algo como adicionar um invólucro quando você Xnfizer uma verificação como if size(arg) == [1,1] ...algo assim. Estou com preguiça de procurar a fonte, mas (espero) não deve ser tão difícil.
FryAmTheEggman #
@FryAmTheEggman De fato, não tenho certeza se esse é o problema (foi por isso que editei rapidamente meu comentário). Se a primeira entrada for um número, a segunda entrada deve ser 1ou 0e não faz diferença se a primeira entrada for interpretada como matriz ou como um número. O verdadeiro problema é que a segunda entrada não pode exceder o tamanho da matriz. "Quantas maneiras existem para escolher 2 elementos de 1 elemento". Nesse caso, a diferença de matriz / número importa: se a primeira entrada for um retorno de matriz [](matriz vazia), se for um retorno de número 0. Acho que vou voltar [], porque depois pforça a outra interpretação.
Luis Mendo
@FryAmTheEggman Acho que vou dividir a função em duas versões. Obrigado novamente!
Luis Mendo
3

Pitão, 15 13 12 11 bytes

*F+1-M.c_Q2
         Q    take input (in format [1,2,3,...])
        _     reverse the array: later we will be subtracting, and we want to
                subtract earlier elements from later elements
      .c  2   combinations of length 2: this gets the correct pairs
    -M        map a[0] - a[1] over each subarray
  +1          prepend a 1 to the array: this does not change the following
                result, but prevents an error on empty array
*F            fold over multiply (multiply all numbers in array)

Obrigado a @FryAmTheEggman e @ Pietu1998 por um byte cada!

Maçaneta da porta
fonte
1
* F sobre uma matriz vazia deve realmente ser 1.
lirtosiast
3

Mathematica, 32 bytes

Det@Table[#^j,{j,0,Length@#-1}]&

Fiquei surpreso ao não encontrar um material para as coisas de Vandermonde. Provavelmente porque é tão fácil fazer isso sozinho.

Este constrói explicitamente a transposição de uma VM e assume seu determinante (que é obviamente o mesmo que o original). Esse método acabou sendo significativamente mais curto do que o uso de qualquer fórmula que eu conheça.

hYPotenuser
fonte
3

Haskell, 34 bytes

f(h:t)=f t*product[x-h|x<-t]
f _=1

Uma solução recursiva. Quando um novo elemento hé anexado à frente, a expressão é multiplicada pelo produto de x-hpara cada elemento xda lista. Obrigado ao Zgarb por 1 byte.

xnor
fonte
2

Matlab, 26 bytes

(não competitivo)

Uso direto de componentes internos. Observe que (mais uma vez) o Matlab's vandercria matrizes de Vandermonde, mas com a ordem das linhas invertidas.

@(v)det(fliplr(vander(v)))
flawr
fonte
2
Por que não competir?
Alex A.
3
Como sou eu quem fez esse desafio, eu só queria fornecer isso para que as pessoas pudessem experimentar seus próprios exemplos.
flawr
Det não é (linhas invertidas) = ​​(-1) ^ n Det (original)?
HYPotenuser #
Não tenho muita certeza, pois as opções determinantes assinam sempre que você alterna duas colunas ou linhas.
flawr
@hYPotenuser - Substitua n por n + 1. Tudo o que você está fazendo é multiplicar por uma matriz P, que é todos os zeros, exceto a diagonal que vai do canto inferior esquerdo para o canto superior direito (então você deseja det (P * vander (v)) = det (P) det (vander (v ))). Por expansão ao longo da primeira coluna ou qualquer outra coisa, você verá det (P) = (-1) ^ (n + 1).
Batman
2

Ferrugem, 86 bytes

|a:Vec<f32>|(0..a.len()).flat_map(|x|(x+1..a.len()).map(move|y|y-x)).fold(1,|a,b|a*b);

Ferrugem, detalhada como sempre ...

A explicação virá mais tarde (embora seja bastante simples).

Maçaneta da porta
fonte
2

Perl, 38 41 bytes

Incluir +1 para -p

Dê os números em uma linha no STDIN. Então, por exemplo, corra como

perl -p vandermonde.pl <<< "1 2 4 8"

Use uma regex maligna para obter o loop duplo:

vandermonde.pl:

$n=1;/(^| ).* (??{$n*=$'-$&;A})/;*_=n
Ton Hospel
fonte
2

JavaScript (ES6), 61 bytes

a=>a.reduce((p,x,i)=>a.slice(0,i).reduce((p,y)=>p*(x-y),p),1)

Eu tentei uma compreensão de matriz (Firefox 30-57) e era 5 bytes mais:

a=>[for(i of a.keys(p=1))for(j of Array(i).keys())p*=a[i]-a[j]]&&p

O loop aninhado chato é provavelmente mais curto.

Neil
fonte
1

Haskell, 53 bytes

 f x=product[x!!j-x!!i|j<-[1..length x-1],i<-[0..j-1]]

Exemplo de uso: f [1,2,4,8,16]->20321280 .

Percorra os índices je iem um loop aninhado e faça uma lista das diferenças dos elementos na posição jei . Faça o produto de todos os elementos na lista.

Outras variantes que se revelaram um pouco mais longas:

f x=product[last l-i|l<-scanl1(++)$pure<$>x,i<-init l], 54 bytes

import Data.List;f i=product[y-x|[x,y]<-subsequences i], 55 bytes

nimi
fonte
1

CJam, 16 bytes

1l~{)1$f-@+:*\}h

Em resposta à postagem de A Simmons ' , apesar da falta de um operador de combinações de CJam, sim, é possível fazer melhor :)

-1 byte graças a @ MartinBüttner.

Experimente online | Suíte de teste

1                   Push 1 to kick off product
 l~                 Read and evaluate input V
   {          }h    Do-while loop until V is empty
    )                 Pop last element of V
     1$               Copy the prefix
       f-             Element-wise subtract each from the popped element
         @+           Add the current product to the resulting array
           :*         Take product to produce new product
             \        Swap, putting V back on top
Sp3000
fonte
0

CJam, 32 bytes

1q~La\{1$f++}/{,2=},{~-}%~]La-:*

Tenho certeza de que alguém pode jogar isso melhor no CJam ... O principal problema é que não consigo ver uma boa maneira de obter os subconjuntos para que consuma a maioria dos meus bytes. Isso gera o conjunto de potência (usando uma idéia de Martin Büttner) e, em seguida, seleciona os elementos comprimento-2.

A Simmons
fonte
0

R , 41 bytes

function(v)det(outer(v,1:sum(v|1)-1,"^"))

Experimente online!

Fiquei surpreso ao não ver uma resposta R aqui!

Giuseppe
fonte