Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Given a vector of n values (x1,x2,x3,...,xn) return the determinant of the corresponding Vandermonde matrix.

This determinant can be written as:

formula

Details

Your program/function has to accept a list of floating point numbers in any convenient format that allows for a variable length, and output the specified determinant.

You can assume that the input as well as the output is within the range of the values your language supports. If you language does not support floating point numbers, you may assume integers.

Some test cases

Note that whenever there are two equal entries, the determinant will be 0 as there are two equal rows in the corresponding Vandermonde matrix. Thanks to @randomra for pointing out this missing testcase.

[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
share|improve this question
    
Can we assume the input is at least of length 2? – Pietu1998 Mar 4 at 21:00
    
@Pietu1998 No, see the first test case. – Alex A. Mar 4 at 21:02
3  
Important test case: [1,2,2,3] => 0: two equal elements in the array, to test if the code checks self-difference (xi-xi) just by comparing to 0. – randomra Mar 5 at 11:10
    
@randomra Thank you, I totally forgot to include one of those. Whenever two entries are equal, the determinant will be 0 as there are two times the same row. – flawr Mar 7 at 20:39
    
@flawr The expected output was clear from your specs. I suggested the test case so answers not prepared for equal numbers could find their mistakes more easily. – randomra Mar 7 at 21:19

15 Answers 15

Jelly, 6 bytes

œc2IFP

œc2 gets all combinations without replacement of length 2. I computes the difference list of each of those pairs, yielding a list like [[1], [2], [3], ..., [1]]. We Flatten and take the Product.

Try it here!

share|improve this answer

Ruby, 49 47 bytes

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

This is a lambda function that accepts a real valued, one-dimensional array and returns a float or an integer depending on the type of the input. To call it, assign it to a variable then do f.call(input).

We get all combinations of size 2 using .combination(2) and get the differences for each pair using .map {|a, b| b - a}. We join the resulting array into a string separated by *, then eval this, which returns the product. If the input has length 1, this will be nil, which is falsey in Ruby, so we can just ||1 at the end to return 1 in this situation. Note that this still works when the product is 0 because for whatever reason 0 is truthy in Ruby.

Verify all test cases online

Saved 2 bytes thanks to Doorknob!

share|improve this answer

Mathematica, 30 bytes

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

This is an anonymous function.

Expanded by Mathematica, it is equivalent to (1 ##1 & ) @@ Apply[#2 - #1 & , Subsets[#1, {2}], {1}] &. 1##& is an equivalent for Times (thanks tips page), which is applied to each distinct pair of elements from the input list, generated by Subsets[list, {2}]. Note that Subsets does not check for uniqueness of elements.

share|improve this answer

J, 13 bytes

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

This is a monadic function that takes in an array and returns a number. Use it like this:

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

Explanation

I explicitly construct the Vandermonde matrix associated with the input array, and then compute its determinant.

-/ .*@(^/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
share|improve this answer
    
I thought whitespace was non-crucial in J... – Cᴏɴᴏʀ O'Bʀɪᴇɴ Mar 5 at 18:02
    
@CᴏɴᴏʀO'Bʀɪᴇɴ The determinant is a special case that requires a separating space, since . is also a modifier character. Same for : on its own. – Zgarb Mar 5 at 18:29
    
Oh! That's cool. – Cᴏɴᴏʀ O'Bʀɪᴇɴ Mar 5 at 18:30
    
@CᴏɴᴏʀO'Bʀɪᴇɴ Actually, I think that is exactly what makes J uncool. J stands for Jot, i.e. a dot or little ring (APL's ), as in jotting with J... The incredibly overloaded . and : (which again is visually the same as two stacked .s) makes J hard to read (for me). How much more so when whitespace next to the dots determine meaning! J's . must be the most overloaded symbol in all of computing history: I count 53 distinct meanings of . and 43 (61 if you count all of _9: to 9:) distinct meanings of :. Yukk. ;-) – Adám Mar 7 at 13:28
    
@Nᴮᶻ it may help to think of the . as its own token; thus, it could, without a white space, be mistaken for another operator. If J is not for you, however, that's understandable. – Cᴏɴᴏʀ O'Bʀɪᴇɴ Mar 7 at 17:50

MATL, 9

!G-qZRQpp

Try it online!

This computes a matrix of all differences and then keeps only the part below the main diagonal, making the other entries 1 so they won't affect the product. The lower triangular function makes the unwanted elements 0, not 1. So we subtract 1, take the lower triangular part, and add 1 back. Then we can take the product of all entries.

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
share|improve this answer
    
It's unfortunate but 2Xn!dp only seems to work with single values when the value is greater than or equal to 2... I had written it myself trying to beat Jelly :P – FryAmTheEggman Mar 4 at 21:42
    
@FryAmTheEggman Awww. You are right. Thanks for the heads-up! – Luis Mendo Mar 4 at 21:48
    
Yeah, I figured that was the problem. I'd consider trying something like adding a wrapper when you get Xn to do a check like if size(arg) == [1,1] ... or something. I'm too lazy to look trough the source, but (hopefully) it shouldn't be that difficult. – FryAmTheEggman Mar 4 at 21:52
    
@FryAmTheEggman In fact I'm not sure that's the problem (that's why I quickly edited my comment). If the first input is a number then the second input should be 1 or 0 and then it makes no difference if the first input is interpreted as array or as a number. The real problem is, second input can't exceed the array size. "How many ways are there to choose 2 elements out of 1 element". In this case the array/number difference matters: if first input is an array return [](empty array), if it's a number return 0. I guess I'll return [], because then p forces the other interpretation – Luis Mendo Mar 4 at 22:01
    
@FryAmTheEggman I think I'll split the function in two versions. Thanks again! – Luis Mendo Mar 4 at 22:44

Pyth, 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)

Thanks to @FryAmTheEggman and @Pietu1998 for a byte each!

share|improve this answer
1  
*F on an empty array should really be 1. – lirtosiast Mar 6 at 16:28

Mathematica, 32 bytes

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

I was surprised not to find a builtin for Vandermonde stuff. Probably because it's so easy to do it oneself.

This one explicitly constructs the transpose of a VM and takes its determinant (which is of course the same as the original's). This method turned out to be significantly shorter than using any formula I know of.

share|improve this answer

Matlab, 26 bytes

(noncompeting)

Straightforward use of builtins. Note that (once again) Matlab's vander creates Vandermonde matrices but with the order of the rows flipped.

@(v)det(fliplr(vander(v)))
share|improve this answer
2  
Why noncompeting? – Alex A. Mar 4 at 20:35
3  
Because I'm the one who made this challenge, I just wanted to provide this so people can try their own examples. – flawr Mar 4 at 20:36
    
Isn't Det(flipped rows) = (-1)^n Det(original)? – hYPotenuser Mar 4 at 21:22
    
I'm not quite sure, as the determinant switches sign whenever you switch two columns or rows. – flawr Mar 4 at 22:24

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

Rust, verbose as usual...

Explanation will come later (it's pretty straightforward, though).

share|improve this answer

JavaScript (ES6), 61 bytes

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

I tried an array comprehension (Firefox 30+) and it was 5 bytes longer:

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

The boring nested loop is probably shorter though.

share|improve this answer

Haskell, 34 bytes

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

A recursive solution. When a new element h is prepended to the front, the expression is multiplied by the product of x-h for each element x of the list. Thanks to Zgarb for 1 byte.

share|improve this answer

Perl, 38 41 bytes

Include +1 for -p

Give the numbers on a line on STDIN. So e.g. run as

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

Use an evil regex to get the double loop:

vandermonde.pl:

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

Haskell, 53 bytes

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

Usage example: f [1,2,4,8,16] -> 20321280.

Go through the indices j and i in a nested loop and make a list of the differences of the elements at position j and i. Make the product of all elements in the list.

Other variants that turned out to be slightly longer:

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

share|improve this answer

CJam, 16 bytes

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

In response to A Simmons' post, despite CJam's lack of a combinations operator, yes it is possible to do better :)

-1 byte thanks to @MartinBüttner.

Try it online | Test suite

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
share|improve this answer

CJam, 32 bytes

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

I'm sure someone can golf this better in CJam... The main issue is that I can't see a good way of getting the subsets so that uses up most of my bytes. This generates the power set (using an idea by Martin Büttner) and then selects the length-2 elements.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.