Determinante Vandermonde


25

Dato un vettore di nvalori (x1,x2,x3,...,xn)restituisce il determinante della matrice Vandermonde corrispondente .

Questo determinante può essere scritto come:

formula

Dettagli

Il programma / funzione deve accettare un elenco di numeri in virgola mobile in qualsiasi formato conveniente che consenta una lunghezza variabile e produrre il determinante specificato.

Puoi presumere che l'input e l'output siano compresi nell'intervallo dei valori supportati dalla tua lingua. Se la tua lingua non supporta i numeri in virgola mobile, puoi assumere numeri interi.

Alcuni casi di test

Si noti che ogni volta che ci sono due voci uguali, il determinante sarà 0dato che ci sono due righe uguali nella matrice Vandermonde corrispondente. Grazie a @randomra per aver segnalato questo testcase mancante.

[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

Possiamo supporre che l'ingresso sia almeno della lunghezza 2?
PurkkaKoodari

@ Pietu1998 No, vedi il primo caso di test.
Alex A.

3
Caso di test importante [1,2,2,3] => 0:: due elementi uguali nell'array, per verificare se il codice controlla l'autodifferenza ( xi-xi) solo confrontandola con0 .
randomra

@randomra Grazie, ho completamente dimenticato di includerne uno. Ogni volta che due voci sono uguali, il determinante sarà 0 in quanto vi sono due volte la stessa riga.
Flawr

1
@flawr L'output previsto era chiaro dalle tue specifiche. Ho suggerito il caso di test in modo che le risposte non preparate per un numero uguale possano trovare più facilmente i loro errori.
randomra

Risposte:


9

Gelatina, 6 byte

œc2IFP

œc2ottiene tutte le combinazioni senza sostituzione della lunghezza 2. Icalcola l'elenco delle differenze di ciascuna di quelle coppie, producendo un elenco simile [[1], [2], [3], ..., [1]]. Noi Flatten e prendiamo il Prodotto.

Provalo qui!


8

Rubino, 49 47 byte

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

Questa è una funzione lambda che accetta un array unidimensionale con valore reale e restituisce un valore float o un numero intero a seconda del tipo di input. Per chiamarlo, assegnalo a una variabile, quindi esegui f.call(input).

Otteniamo tutte le combinazioni della taglia 2 usando .combination(2)e otteniamo le differenze per ogni coppia usando .map {|a, b| b - a}. *Quindi uniamo l'array risultante in una stringa separata daeval questa, che restituisce il prodotto. Se l'input ha lunghezza 1, questo sarà nil, il che è falso in Ruby, quindi possiamo solo ||1alla fine per restituire 1 in questa situazione. Nota che funziona ancora quando il prodotto è 0 perché per qualsiasi motivo 0 è vero in Ruby.

Verifica tutti i casi di test online

Salvato 2 byte grazie a Doorknob!


7

Mathematica, 30 byte

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

Questa è una funzione anonima.

Ampliato da Mathematica, è equivalente a (1 ##1 & ) @@ Apply[#2 - #1 & , Subsets[#1, {2}], {1}] &. 1##&è un equivalente di Times(pagina dei suggerimenti grazie), che viene applicato a ciascuna coppia distinta di elementi dall'elenco di input, generata da Subsets[list, {2}]. Si noti che Subsetsnon verifica l'unicità degli elementi.


5

J, 13 byte

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

Questa è una funzione monadica che accetta un array e restituisce un numero. Usalo in questo modo:

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

Spiegazione

Costruisco esplicitamente la matrice Vandermonde associata all'array di input e quindi ne calcolo il 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

Pensavo che lo spazio bianco non fosse cruciale in J ...
Conor O'Brien il

@ CᴏɴᴏʀO'Bʀɪᴇɴ Il determinante è un caso speciale che richiede uno spazio di separazione, poiché .è anche un carattere modificatore. Lo stesso per :conto suo.
Zgarb

Oh! Questo è figo.
Conor O'Brien,

@ CᴏɴᴏʀO'Bʀɪᴇɴ In realtà, penso che sia esattamente ciò che rende J uncool. J sta per Jot, vale a dire un punto o un piccolo anello (APL ), come nel jotting con J ... L'incredibilmente sovraccarico .e :(che di nuovo è visivamente lo stesso di due .s sovrapposti ) rende J difficile da leggere (per me). Quanto più quando gli spazi bianchi accanto ai punti determinano il significato! J .deve essere il simbolo più sovraccarico di tutta la storia dell'informatica: conto 53 significati distinti di .e 43 (61 se conti tutto _9:a 9:) significati distinti di :. Yukk. ;-)
Adám

@ Nᴮᶻ può essere d'aiuto pensare al. come segno distintivo; quindi, senza uno spazio bianco, potrebbe essere scambiato per un altro operatore. Se J non è per te, tuttavia, è comprensibile.
Conor O'Brien,

4

MATL , 9

!G-qZRQpp

Provalo online!

Questo calcola una matrice di tutte le differenze e quindi mantiene solo la parte sotto la diagonale principale, facendo le altre voci in 1modo che non influenzino il prodotto. La funzione triangolare inferiore rende gli elementi indesiderati 0, no 1. Quindi sottraggiamo 1, prendiamo la parte triangolare inferiore e aggiungiamo di 1nuovo. Quindi possiamo prendere il prodotto di tutte le voci.

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

È sfortunato, ma 2Xn!dpsembra funzionare solo con valori singoli quando il valore è maggiore o uguale a 2 ... L'ho scritto io stesso cercando di battere Jelly: P
FryAmTheEggman

@FryAmTheEggman Awww. Hai ragione. Grazie per il testa a testa!
Luis Mendo,

Sì, ho pensato che fosse questo il problema. Considererei di provare qualcosa come aggiungere un wrapper quando riesci Xna fare un controllo simile if size(arg) == [1,1] ...o qualcosa del genere. Sono troppo pigro per guardare attraverso la fonte, ma (si spera) non dovrebbe essere così difficile.
FryAmTheEggman

@FryAmTheEggman In effetti non sono sicuro che sia il problema (ecco perché ho modificato rapidamente il mio commento). Se il primo input è un numero, il secondo input dovrebbe essere 1o 0e quindi non fa alcuna differenza se il primo input viene interpretato come array o come numero. Il vero problema è che il secondo input non può superare la dimensione dell'array. "Quanti modi ci sono per scegliere 2 elementi su 1 elemento". In questo caso la differenza di matrice / numero è importante: se il primo input è un ritorno di matrice [](matrice vuota), se è un ritorno di numero 0. Immagino che tornerò [], perché poi pforza l'altra interpretazione
Luis Mendo il

@FryAmTheEggman Penso che dividerò la funzione in due versioni. Grazie ancora!
Luis Mendo,

3

Pyth, 15 13 12 11 byte

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

Grazie a @FryAmTheEggman e @ Pietu1998 per un byte ciascuno!


1
* F su un array vuoto dovrebbe essere veramente 1.
lirtosiast

3

Mathematica, 32 byte

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

Sono stato sorpreso di non trovare un prodotto integrato per le cose di Vandermonde. Probabilmente perché è così facile farlo da soli.

Questo costruisce esplicitamente il recepimento di una VM e ne prende il determinante (che è ovviamente lo stesso dell'originale). Questo metodo si è rivelato significativamente più breve rispetto all'uso di qualsiasi formula che conosco.


3

Haskell, 34 byte

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

Una soluzione ricorsiva. Quando un nuovo elemento hviene anteposto, l'espressione viene moltiplicata per il prodotto di x-hper ciascun elemento xdell'elenco. Grazie a Zgarb per 1 byte.


2

Matlab, 26 byte

(Noncompeting)

Uso diretto dei builtin. Nota che (ancora una volta) Matlab's vandercrea matrici Vandermonde ma con l'ordine delle righe capovolto.

@(v)det(fliplr(vander(v)))

2
Perché non competere?
Alex A.

3
Dato che sono io quello che ha fatto questa sfida, volevo solo fornire questo in modo che le persone possano provare i propri esempi.
Flawr

Det (righe capovolte) = (-1) ^ n Det (originale)?
hYPotenuser

Non sono del tutto sicuro, poiché gli interruttori determinanti firmano ogni volta che si cambiano due colonne o righe.
flawr

@hYPotenuser - Sostituisci n con n + 1. Tutto quello che stai facendo è moltiplicare per una matrice P che è tutti zeri ad eccezione della diagonale che va dal basso a sinistra in alto a destra (quindi vuoi det (P * vander (v)) = det (P) det (vander (v ))). Espandendo lungo la prima colonna o qualsiasi altra cosa, vedrai det (P) = (-1) ^ (n + 1).
Batman,

2

Ruggine, 86 byte

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

Ruggine, verbosa come al solito ...

La spiegazione arriverà più tardi (è piuttosto semplice, però).


2

Perl, 38 41 byte

Includi +1 per -p

Indica i numeri su una riga su STDIN. Quindi es. Corri come

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

Usa una malvagia regex per ottenere il doppio loop:

vandermonde.pl:

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

2

JavaScript (ES6), 61 byte

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

Ho provato una comprensione dell'array (Firefox 30-57) ed era più lungo di 5 byte:

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

Il loop nidificato noioso è probabilmente più breve però.


1

Haskell, 53 byte

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

Esempio di utilizzo: f [1,2,4,8,16] -> 20321280.

Passare attraverso gli indici je iin un ciclo nidificato e fare un elenco delle differenze degli elementi in posizione jei . Crea il prodotto di tutti gli elementi nell'elenco.

Altre varianti che si sono rivelate leggermente più lunghe:

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

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


1

CJam, 16 byte

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

In risposta al post di A Simmons , nonostante la mancanza di un operatore di combinazioni di CJam, sì, è possibile fare di meglio :)

-1 byte grazie a @ MartinBüttner.

Provalo online | Suite di test

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

0

CJam, 32 byte

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

Sono sicuro che qualcuno può giocare a golf così bene in CJam ... Il problema principale è che non riesco a vedere un buon modo per ottenere i sottoinsiemi che consumano la maggior parte dei miei byte. Questo genera il gruppo elettrogeno (usando un'idea di Martin Büttner) e quindi seleziona gli elementi length-2.



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.