Vandermonde Déterminant

25

Étant donné un vecteur de nvaleurs, (x1,x2,x3,...,xn)renvoyer le déterminant de la matrice de Vandermonde correspondante .

Ce déterminant peut s'écrire:

formule

Détails

Votre programme / fonction doit accepter une liste de nombres à virgule flottante dans n'importe quel format pratique qui permet une longueur variable et produire le déterminant spécifié.

Vous pouvez supposer que l'entrée ainsi que la sortie sont dans la plage des valeurs prises en charge par votre langue. Si votre langue ne prend pas en charge les nombres à virgule flottante, vous pouvez supposer des nombres entiers.

Quelques cas de test

Notez que chaque fois qu'il y a deux entrées égales, le déterminant sera 0comme il y a deux lignes égales dans la matrice Vandermonde correspondante. Merci à @randomra d'avoir signalé ce testcase manquant.

[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
la source
Pouvons-nous supposer que l'entrée est au moins de longueur 2?
PurkkaKoodari
@ Pietu1998 Non, voir le premier cas de test.
Alex A.
3
Cas de test important [1,2,2,3] => 0:: deux éléments égaux dans le tableau, pour tester si le code vérifie l'auto-différence ( xi-xi) simplement en comparant à 0.
randomra
@randomra Merci, j'ai totalement oublié d'en inclure un. Chaque fois que deux entrées sont égales, le déterminant sera 0 car il y a deux fois la même ligne.
flawr
1
@flawr La sortie attendue était claire d'après vos spécifications. J'ai suggéré le cas de test pour que les réponses non préparées pour des nombres égaux puissent trouver plus facilement leurs erreurs.
randomra

Réponses:

9

Gelée, 6 octets

œc2IFP

œc2obtient toutes les combinaisons sans remplacement de la longueur 2. Icalcule la liste des différences de chacune de ces paires, donnant une liste comme [[1], [2], [3], ..., [1]]. Nous Flatten et prenons le Product.

Essayez-le ici!

Lynn
la source
8

Rubis, 49 47 octets

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

Il s'agit d'une fonction lambda qui accepte un tableau unidimensionnel à valeur réelle et renvoie un flottant ou un entier selon le type d'entrée. Pour l'appeler, affectez-le à une variable puis faites f.call(input).

Nous obtenons toutes les combinaisons de taille 2 en utilisant .combination(2)et obtenons les différences pour chaque paire en utilisant .map {|a, b| b - a}. Nous joignons le tableau résultant dans une chaîne séparée par *, puis evalcelle-ci, qui renvoie le produit. Si l'entrée a une longueur 1, ce sera nil, ce qui est falsey en Ruby, donc nous pouvons juste ||1à la fin retourner 1 dans cette situation. Notez que cela fonctionne toujours lorsque le produit est 0 car pour une raison quelconque, 0 est vrai en Ruby.

Vérifiez tous les cas de test en ligne

Sauvegardé 2 octets grâce à Doorknob!

Alex A.
la source
7

Mathematica, 30 octets

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

Il s'agit d'une fonction anonyme.

Développé par Mathematica, il est équivalent à (1 ##1 & ) @@ Apply[#2 - #1 & , Subsets[#1, {2}], {1}] &. 1##&est un équivalent de Times(page de conseils de remerciement), qui est appliqué à chaque paire distincte d'éléments de la liste d'entrée, générée par Subsets[list, {2}]. Notez que Subsetscela ne vérifie pas l'unicité des éléments.

feersum
la source
5

J, 13 octets

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

Il s'agit d'une fonction monadique qui prend un tableau et renvoie un nombre. Utilisez-le comme ceci:

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

Explication

Je construis explicitement la matrice Vandermonde associée au tableau d'entrée, puis calcule son déterminant.

-/ .*@(^/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
la source
Je pensais que les espaces blancs n'étaient pas cruciaux en J ...
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Le déterminant est un cas particulier qui nécessite un espace de séparation, puisqu'il .s'agit également d'un caractère modificateur. Pareil pour :lui-même.
Zgarb
Oh! C'est super.
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ En fait, je pense que c'est exactement ce qui rend J cool. J signifie Jot, c'est-à-dire un point ou un petit anneau (APL ), comme en griffonnant avec J ... L'incroyablement surchargé .et :(qui est visuellement le même que deux .s empilés ) rend J difficile à lire (pour moi). A plus forte raison lorsque les espaces à côté des points déterminent le sens! J ce .doit être le symbole le plus surchargé dans toute l'histoire informatique: je compte 53 significations distinctes .et 43 (61 si l' on compte tous _9:à 9:) significations distinctes :. Yukk. ;-)
Adám
@ Nᴮᶻ il peut être utile de penser à la. comme son propre jeton; ainsi, il pourrait, sans espace blanc, être confondu avec un autre opérateur. Si J n'est pas pour vous, c'est compréhensible.
Conor O'Brien
4

MATL , 9

!G-qZRQpp

Essayez-le en ligne!

Cela calcule une matrice de toutes les différences, puis ne conserve que la partie en dessous de la diagonale principale, ce qui rend les autres entrées 1afin qu'elles n'affectent pas le produit. La fonction triangulaire inférieure rend les éléments indésirables 0, non 1. Donc on soustrait 1, on prend la partie triangulaire inférieure, et on rajoute 1. Ensuite, nous pouvons prendre le produit de toutes les entrées.

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
la source
C'est malheureux mais 2Xn!dpne semble fonctionner avec des valeurs uniques que lorsque la valeur est supérieure ou égale à 2 ... Je l'avais écrit moi-même en essayant de battre Jelly: P
FryAmTheEggman
@FryAmTheEggman Awww. Vous avez raison. Merci pour l'information!
Luis Mendo
Ouais, je pensais que c'était le problème. J'envisagerais d'essayer quelque chose comme l'ajout d'un wrapper lorsque vous Xnfaites une vérification comme if size(arg) == [1,1] ...ou quelque chose. Je suis trop paresseux pour regarder à travers la source, mais (espérons-le) ça ne devrait pas être si difficile.
FryAmTheEggman
@FryAmTheEggman En fait, je ne suis pas sûr que ce soit le problème (c'est pourquoi j'ai rapidement modifié mon commentaire). Si la première entrée est un nombre, la deuxième entrée doit être1 ou 0et cela ne fait aucune différence si la première entrée est interprétée comme un tableau ou comme un nombre. Le vrai problème est que la deuxième entrée ne peut pas dépasser la taille du tableau. "Combien y a-t-il de façons de choisir 2 éléments sur 1 élément". Dans ce cas, la différence tableau / nombre est importante: si la première entrée est un retour de tableau [](tableau vide), s'il s'agit d'un retour de nombre 0. Je suppose que je reviendrai [], car alors pforce l'autre interprétation
Luis Mendo
@FryAmTheEggman Je pense que je vais diviser la fonction en deux versions. Merci encore!
Luis Mendo
3

Pyth, 15 13 12 11 octets

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

Merci à @FryAmTheEggman et @ Pietu1998 pour un octet chacun!

Poignée de porte
la source
1
* F sur un tableau vide devrait vraiment être 1.
lirtosiast
3

Mathematica, 32 octets

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

J'ai été surpris de ne pas trouver de builtin pour les trucs Vandermonde. Probablement parce que c'est si facile de le faire soi-même.

Celui-ci construit explicitement la transposition d'une VM et prend son déterminant (qui est bien sûr le même que celui de l'original). Cette méthode s'est avérée être beaucoup plus courte que l'utilisation de toute formule que je connaisse.

hYPotenuser
la source
3

Haskell, 34 octets

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

Une solution récursive. Lorsqu'un nouvel élément hest ajouté au début, l'expression est multipliée par le produit de x-hpour chaque élément xde la liste. Merci à Zgarb pour 1 octet.

xnor
la source
2

Matlab, 26 octets

(non compétitif)

Utilisation simple des fonctions intégrées. Notez que (encore une fois) Matlab vandercrée des matrices Vandermonde mais avec l'ordre des lignes inversées.

@(v)det(fliplr(vander(v)))
flawr
la source
2
Pourquoi non compétitif?
Alex A.
3
Parce que c'est moi qui ai fait ce défi, je voulais juste fournir ceci pour que les gens puissent essayer leurs propres exemples.
flawr
N'est-ce pas Det (lignes inversées) = (-1) ^ n Det (original)?
hYPotenuser
Je ne suis pas tout à fait sûr, car les commutateurs déterminants signent chaque fois que vous changez deux colonnes ou lignes.
flawr
@hYPotenuser - Remplacez n par n + 1. Tout ce que vous faites est de multiplier par une matrice P qui est tous des zéros à l'exception de la diagonale allant du bas à gauche vers le haut à droite (vous voulez donc det (P * vander (v)) = det (P) det (vander (v ))). Par expansion le long de la première colonne ou autre, vous verrez det (P) = (-1) ^ (n + 1).
Batman le
2

Rouille, 86 octets

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

Rouille, verbeuse comme d'habitude ...

L'explication viendra plus tard (c'est assez simple, cependant).

Poignée de porte
la source
2

Perl, 38 41 octets

Inclure +1 pour -p

Donnez les chiffres sur une ligne sur STDIN. Donc, par exemple, exécutez

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

Utilisez un regex maléfique pour obtenir la double boucle:

vandermonde.pl:

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

JavaScript (ES6), 61 octets

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

J'ai essayé une compréhension de tableau (Firefox 30-57) et c'était 5 octets de plus:

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

La boucle imbriquée ennuyeuse est probablement plus courte cependant.

Neil
la source
1

Haskell, 53 octets

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

Exemple d'utilisation: f [1,2,4,8,16]->20321280 .

Parcourez les indices jet idans une boucle imbriquée et faites une liste des différences des éléments en position jeti . Faites le produit de tous les éléments de la liste.

Autres variantes qui se sont révélées être légèrement plus longues:

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

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

nimi
la source
1

CJam, 16 octets

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

En réponse au message de A Simmons , malgré le manque d'opérateur de combinaisons de CJam, oui, il est possible de faire mieux :)

-1 octet grâce à @ MartinBüttner.

Essayez-le en ligne | Suite de tests

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
la source
0

CJam, 32 octets

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

Je suis sûr que quelqu'un peut mieux jouer au golf dans CJam ... Le principal problème est que je ne vois pas un bon moyen d'obtenir les sous-ensembles afin que la plupart de mes octets soient utilisés. Cela génère le jeu de puissance (en utilisant une idée de Martin Büttner), puis sélectionne les éléments de longueur 2.

A Simmons
la source
0

R , 41 octets

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

Essayez-le en ligne!

J'ai été surpris de ne pas voir de réponse R ici!

Giuseppe
la source