Vandermonde Determinant

25

Diberikan vektor nnilai (x1,x2,x3,...,xn)mengembalikan penentu matriks Vandermonde yang sesuai .

Penentu ini dapat ditulis sebagai:

rumus

Detail

Program / fungsi Anda harus menerima daftar angka floating point dalam format apa pun yang memungkinkan untuk panjang variabel, dan output penentu yang ditentukan.

Anda dapat mengasumsikan bahwa input serta output berada dalam kisaran nilai yang didukung bahasa Anda. Jika bahasa Anda tidak mendukung angka floating point, Anda dapat mengasumsikan bilangan bulat.

Beberapa test case

Perhatikan bahwa setiap kali ada dua entri yang sama, determinannya adalah 0karena ada dua baris yang sama dalam matriks Vandermonde yang sesuai. Terima kasih kepada @randomra karena menunjukkan testcase yang hilang ini.

[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
cacat
sumber
Bisakah kita berasumsi bahwa inputnya setidaknya memiliki panjang 2?
PurkkaKoodari
@ Pietu1998 Tidak, lihat test case pertama.
Alex A.
3
Kasus uji penting [1,2,2,3] => 0:: dua elemen yang sama dalam array, untuk menguji apakah kode memeriksa perbedaan sendiri ( xi-xi) hanya dengan membandingkan 0.
randomra
@randomra Terima kasih, saya benar-benar lupa untuk memasukkan salah satunya. Setiap kali dua entri sama, determinannya adalah 0 karena ada dua kali baris yang sama.
flawr
1
@ flawr Output yang diharapkan jelas dari spesifikasi Anda. Saya menyarankan test case sehingga jawaban yang tidak siap untuk angka yang sama dapat menemukan kesalahan mereka dengan lebih mudah.
randomra

Jawaban:

9

Jelly, 6 byte

œc2IFP

œc2mendapatkan semua kombinasi tanpa penggantian panjang 2. Imenghitung daftar perbedaan dari masing-masing pasangan, menghasilkan daftar seperti [[1], [2], [3], ..., [1]]. Kami Flatten dan mengambil Product.

Coba di sini!

Lynn
sumber
8

Ruby, 49 47 byte

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

Ini adalah fungsi lambda yang menerima array satu dimensi yang bernilai nyata dan mengembalikan float atau integer tergantung pada jenis input. Untuk memanggilnya, tetapkan ke variabel lalu lakukan f.call(input).

Kami mendapatkan semua kombinasi ukuran 2 menggunakan .combination(2)dan mendapatkan perbedaan untuk setiap pasangan menggunakan .map {|a, b| b - a}. Kami bergabung dengan array yang dihasilkan menjadi string yang dipisahkan oleh *, lalu evalini, yang mengembalikan produk. Jika input memiliki panjang 1, ini akan menjadi nil, yang merupakan kesalahan dalam Ruby, jadi kita bisa saja ||1pada akhirnya untuk mengembalikan 1 dalam situasi ini. Perhatikan bahwa ini masih berfungsi ketika produk 0 karena untuk alasan apa pun 0 benar di Ruby.

Verifikasi semua kasus uji online

Disimpan 2 byte berkat Doorknob!

Alex A.
sumber
7

Mathematica, 30 byte

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

Ini adalah fungsi anonim.

Diperluas oleh Mathematica, itu setara dengan (1 ##1 & ) @@ Apply[#2 - #1 & , Subsets[#1, {2}], {1}] &. 1##&adalah setara dengan Times(halaman tips terima kasih), yang diterapkan pada setiap pasangan elemen yang berbeda dari daftar input, yang dihasilkan oleh Subsets[list, {2}]. Perhatikan bahwa Subsetstidak memeriksa keunikan elemen.

feersum
sumber
5

J, 13 byte

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

Ini adalah fungsi monadik yang mengambil array dan mengembalikan angka. Gunakan seperti ini:

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

Penjelasan

Saya secara eksplisit membangun matriks Vandermonde yang terkait dengan array input, dan kemudian menghitung determinannya.

-/ .*@(^/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
sumber
Saya pikir spasi tidak penting di ...
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Penentu adalah kasus khusus yang memerlukan ruang pemisah, karena .juga merupakan karakter pengubah. Sama untuknya :sendiri.
Zgarb
Oh! Itu keren.
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Sebenarnya, saya pikir itulah yang membuat J tidak keren. J adalah singkatan dari Jot, yaitu titik atau cincin kecil (APL ), seperti dalam penulisan dengan J ... Yang sangat kelebihan beban .dan :(yang lagi-lagi secara visual sama dengan dua .s yang ditumpuk ) membuat J sulit dibaca (untuk saya). Terlebih lagi ketika spasi putih di sebelah titik-titik menentukan makna! J .harus simbol yang paling kelebihan beban dalam sejarah komputasi: Saya menghitung 53 makna yang berbeda .dan 43 (61 jika Anda menghitung semua _9:untuk 9:) makna yang berbeda :. Yukk. ;-)
Adm
@ Nᴮᶻ mungkin ada baiknya memikirkan. sebagai tokennya sendiri; dengan demikian, itu bisa, tanpa ruang putih, keliru untuk operator lain. Namun, jika J bukan untuk Anda, itu bisa dimengerti.
Conor O'Brien
4

MATL , 9

!G-qZRQpp

Cobalah online!

Ini menghitung matriks dari semua perbedaan dan kemudian hanya menyimpan bagian di bawah diagonal utama, membuat entri lain 1sehingga mereka tidak akan mempengaruhi produk. Fungsi segitiga bawah membuat elemen yang tidak diinginkan 0, tidak 1. Jadi kita kurangi 1, ambil bagian segitiga bawah, dan tambahkan 1kembali. Lalu kita bisa mengambil produk dari semua entri.

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
sumber
Sangat disayangkan tetapi 2Xn!dptampaknya hanya berfungsi dengan nilai tunggal ketika nilainya lebih dari atau sama dengan 2 ... Saya telah menulisnya sendiri mencoba untuk mengalahkan Jelly: P
FryAmTheEggman
@FryAmTheEggman Awww. Kamu benar. Terimakasih atas peringatannya!
Luis Mendo
Ya, saya pikir itu masalahnya. Saya akan mempertimbangkan mencoba sesuatu seperti menambahkan pembungkus ketika Anda bisa Xnmelakukan pemeriksaan suka if size(arg) == [1,1] ...atau sesuatu. Saya terlalu malas untuk melihat dari sumbernya, tapi (semoga) itu tidak terlalu sulit.
FryAmTheEggman
@FryAmTheEggman Sebenarnya saya tidak yakin itu masalahnya (itu sebabnya saya cepat mengedit komentar saya). Jika input pertama adalah angka maka input kedua harus 1atau 0dan tidak ada bedanya jika input pertama diartikan sebagai array atau sebagai angka. Masalah sebenarnya adalah, input kedua tidak dapat melebihi ukuran array. "Ada berapa cara untuk memilih 2 elemen dari 1 elemen". Dalam hal ini perbedaan array / angka penting: jika input pertama adalah pengembalian array [](array kosong), jika itu adalah angka kembali 0. Saya kira saya akan kembali [], karena kemudian pmemaksa interpretasi lain
Luis Mendo
@FryAmTheEggman Saya pikir saya akan membagi fungsi menjadi dua versi. Terima kasih lagi!
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)

Terima kasih kepada @FryAmTheEggman dan @ Pietu1998 untuk setiap byte!

Gagang pintu
sumber
1
* F pada array kosong harus benar-benar 1.
lirtosiast
3

Mathematica, 32 byte

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

Saya terkejut tidak menemukan builtin untuk hal-hal Vandermonde. Mungkin karena begitu mudah melakukannya sendiri.

Yang satu ini secara eksplisit membangun transpose dari suatu VM dan mengambil determinannya (yang tentu saja sama dengan yang asli). Metode ini ternyata jauh lebih singkat daripada menggunakan formula apa pun yang saya tahu.

hYPotenuser
sumber
3

Haskell, 34 byte

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

Solusi rekursif. Ketika elemen baru hditambahkan ke depan, ekspresi dikalikan dengan produk x-huntuk setiap elemen xdaftar. Terima kasih kepada Zgarb untuk 1 byte.

Tidak
sumber
2

Matlab, 26 byte

(tidak bersaing)

Penggunaan langsung builtin. Perhatikan bahwa (sekali lagi) Matlab vandermenciptakan matriks Vandermonde tetapi dengan urutan baris terbalik.

@(v)det(fliplr(vander(v)))
cacat
sumber
2
Mengapa tidak bersaing?
Alex A.
3
Karena saya yang membuat tantangan ini, saya hanya ingin memberikan ini sehingga orang dapat mencoba contoh mereka sendiri.
flawr
Bukankah Det (baris terbalik) = (-1) ^ n Det (asli)?
hYPotenuser
Saya tidak yakin, karena penentu beralih masuk setiap kali Anda mengganti dua kolom atau baris.
flawr
@hYPotenuser - Ganti n dengan n +1. Yang Anda lakukan adalah mengalikan dengan matriks P yang semuanya nol kecuali untuk diagonal dari kiri bawah ke kanan atas (jadi Anda ingin det (P * vander (v)) = det (P) det (vander (v ))). Dengan ekspansi di sepanjang kolom pertama atau apa pun, Anda akan melihat det (P) = (-1) ^ (n + 1).
Batman
2

Rust, 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);

Karat, bertele-tele seperti biasa ...

Penjelasan akan datang nanti (cukup mudah, sih).

Gagang pintu
sumber
2

Perl, 38 41 byte

Sertakan +1 untuk -p

Berikan nomor pada garis di STDIN. Jadi misalnya dijalankan

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

Gunakan regex jahat untuk mendapatkan loop ganda:

vandermonde.pl:

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

JavaScript (ES6), 61 byte

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

Saya mencoba pemahaman array (Firefox 30-57) dan panjangnya 5 byte:

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

Nested loop yang membosankan mungkin lebih pendek.

Neil
sumber
1

Haskell, 53 byte

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

Contoh penggunaan: f [1,2,4,8,16]-> 20321280.

Pergi melalui indeks jdani dalam loop bersarang dan buat daftar perbedaan elemen pada posisi jdan i. Buat produk dari semua elemen dalam daftar.

Varian lain yang ternyata sedikit lebih panjang:

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

nimi
sumber
1

CJam, 16 byte

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

Menanggapi posting A Simmons , meskipun CJam tidak memiliki operator kombinasi, ya dimungkinkan untuk melakukan yang lebih baik :)

-1 byte terima kasih kepada @ MartinBüttner.

Cobalah online | Suite uji

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
sumber
0

CJam, 32 byte

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

Saya yakin seseorang dapat bermain golf ini lebih baik di CJam ... Masalah utamanya adalah saya tidak bisa melihat cara yang baik untuk mendapatkan subset sehingga menghabiskan sebagian besar byte saya. Ini menghasilkan set daya (menggunakan ide oleh Martin Büttner) dan kemudian memilih elemen panjang-2.

A Simmons
sumber
0

R , 41 byte

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

Cobalah online!

Saya terkejut tidak melihat jawaban R di sini!

Giuseppe
sumber