ヴァンダーモンドの決定要因


25

n値のベクトルが与えられる(x1,x2,x3,...,xn)と、対応するVandermonde行列の行列式を返します。

この決定要因は次のように記述できます。

式

詳細

プログラム/関数は、可変長を可能にする便利な形式の浮動小数点数のリストを受け入れ、指定された行列式を出力する必要があります。

入力と出力は、言語がサポートする値の範囲内にあると想定できます。ご使用の言語が浮動小数点数をサポートしていない場合、整数と見なすことができます。

いくつかのテストケース

2つの等しいエントリ0が存在する場合、対応するVandermondeマトリックスには2つの等しい行があるため、行列式が決定されることに注意してください。この欠落したテストケースを指摘してくれた@randomraに感謝します。

[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

入力が少なくとも長さ2であると想定できますか?
PurkkaKoodari

@ Pietu1998いいえ、最初のテストケースを参照してください。
アレックスA.

3
重要なテストケース:[1,2,2,3] => 0:試験にアレイ内の2つの等しい要素、コードチェック自己差IF( xi-xi)だけを比較することによって0
ランダラ

@randomraありがとう、私はそれらの1つを含めるのを完全に忘れていました。2つのエントリが等しい場合、同じ行が2回あるため、行列式は0になります。
flawr

1
@flawr期待される出力は仕様から明らかでした。私はテストケースを提案しました。そうすれば、等しい数に対応していない回答がより簡単に間違いを見つけられます。
ランダラ

回答:


9

ゼリー、6バイト

œc2IFP

œc2長さ2の置換なしですべての組み合わせを取得します。これらIの各ペアの差分リストを計算し、のようなリストを生成します[[1], [2], [3], ..., [1]]。私たちはFラテンを取り、P製品を取ります。

ここで試してみてください!


8

ルビー、49 47バイト

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

これは、実数値の1次元配列を受け入れ、入力のタイプに応じてfloatまたは整数を返すラムダ関数です。呼び出すには、変数に割り当ててから実行しますf.call(input)

を使用.combination(2)してサイズ2のすべての組み合わせを取得し、を使用して各ペアの差を取得し.map {|a, b| b - a}ます。結果の配列を、で区切られた文字列に結合し*、次にeval、これが製品を返します。入力の長さが1の場合、これはになりますnil。これはRubyでは偽であるため||1、この状況で最後に1を返すことができます。これは、製品が0の場合でも機能することに注意してください。理由はなんであれ、Rubyでは0が真実だからです。

すべてのテストケースをオンラインで検証する

Doorknobのおかげで2バイト節約できました!


7

Mathematica、30バイト

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

これは匿名関数です。

Mathematicaによって拡張され、に相当し(1 ##1 & ) @@ Apply[#2 - #1 & , Subsets[#1, {2}], {1}] &ます。1##&は、Times(thanks tips page)に相当します。これは、によって生成された入力リストの要素の各個別のペアに適用されSubsets[list, {2}]ます。Subsets要素の一意性をチェックしないことに注意してください。


5

J、13バイト

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

これは、配列を取り込んで数値を返す単項関数です。次のように使用します。

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

説明

入力配列に関連付けられたVandermonde行列を明示的に構築し、その行列式を計算します。

-/ .*@(^/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

私は... Jに非決定的なだった空白と思った
コナー・オブライエン

@CᴏɴᴏʀO'Bʀɪᴇɴ行列式は.修飾子文字でもあるため、分離スペースを必要とする特殊なケースです。:単独でも同じです。
ズガルブ

ああ!カッコいい。
コナーオブライエン

@CᴏɴᴏʀO'Bʀɪᴇɴ実際、それがまさにJを冷静にしていると思います。Jは、(APLの、Jotのためにすなわち、A点または小さなリングスタンド)、のようにJとjotting ...信じられないほど、オーバーロード.して:(再び視覚的に積層された2つのと同じである.S)Jハードは(私のために)読みすることができます。ドットの隣の空白が意味を決定するとき、それだけではありません!Jさんは、.コンピューティングの歴史のすべての中で最もオーバーロードされたシンボルである必要があります:私は53件の個別の意味を数える.(あなたがすべてのカウント場合は61と43の_9:への9:の明確な意味を):。ユック。;-)
アダム

@Nᴮᶻを考えるのに役立つかもしれません。独自のトークンとして。したがって、空白なしで別の演算子と間違えられる可能性があります。Jがあなたのためではない場合、しかし、それは理解できます。
コナーオブライエン

4

MATL、9

!G-qZRQpp

オンラインでお試しください!

これにより、すべての差のマトリックスが計算され、メインの対角線より下の部分のみが保持され、他のエントリ1が製品に影響を与えないようになります。下三角関数は、0ではなく不要な要素を作成し1ます。だから、減算し1、下三角部分を取り、加算し1ます。その後、すべてのエントリの積を取得できます。

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

残念ですが2Xn!dp、値が2以上の場合にのみ単一の値で動作するようです。ジェリーを倒そうとして自分で書いたのです。P
FryAmTheEggman

@FryAmTheEggman Awww。あなたが正しいです。ヘッドアップをありがとう!
ルイスメンドー

うん、それが問題だと思った。のようなXnチェックを行うようになったら、ラッパーを追加するなどのことを試してみるとif size(arg) == [1,1] ...よいでしょう。私はソースを覗くのが面倒ですが、(うまくいけば)それほど難しくないはずです。
FryAmTheEggman

@FryAmTheEggman実際、それが問題なのかどうかわかりません(だから私はすぐにコメントを編集しました)。最初の入力が数値の場合、2番目の入力はまたはである1必要が0あり、最初の入力が配列または数値として解釈されても違いはありません。実際の問題は、2番目の入力が配列サイズを超えることはできないということです。「1つの要素から2つの要素を選択する方法はいくつありますか」。この場合、配列/数値の違いが重要です:最初の入力が配列の戻り値[](空の配列)の場合、それが数値の戻り値の場合0。私は、他の解釈を強制する[]ので、戻ってくると思いますp
ルイスメンドー

@FryAmTheEggman関数を2つのバージョンに分割すると思います。再度、感謝します!
ルイスメンドー

3

Pyth、15 13 12 11バイト

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

それぞれ1バイトの@FryAmTheEggman@ Pietu1998に感謝します!


1
*空の配列のFは実際には1でなければなりません。
lirtosiast

3

Mathematica、32バイト

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

Vandermondeの組み込み機能が見つからないことに驚きました。おそらく、自分でそれを行うのはとても簡単だからです。

これは、VMの転置を明示的に構築し、その決定要因を取得します(もちろん元のものと同じです)。この方法は、私が知っている式を使用するよりも大幅に短いことがわかりました。


3

Haskell、34バイト

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

再帰的なソリューション。新しい要素hが先頭に追加されると、式にリストのx-h各要素の積が乗算されxます。1バイトのZgarbに感謝します。


2

Matlab、26バイト

(非競合)

組み込みの簡単な使用。(もう一度)Matlab vanderはVandermonde行列を作成しますが、行の順序が反転していることに注意してください。

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

2
競合しない理由
アレックスA.

3
私はこの挑戦をした人なので、人々が自分の例を試すことができるようにこれを提供したかっただけです。
-flawr

Det(flipped rows)=(-1)^ n Det(original)ではないですか?
hYPotenuser

2つの列または行を切り替えるたびに、行列式が符号を切り替えるため、よくわかりません。
-flawr

@hYPotenuser-nをn + 1に置き換えます。あなたがしているのは、左下から右上に向かう対角線を除いてすべてゼロである行列Pを乗算することです(したがって、det(P * vander(v))= det(P)det(vander(v )))。最初の列などに沿って展開すると、det(P)=(-1)^(n + 1)が表示されます。
バットマン

2

さび、86バイト

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

さび、いつものように冗長...

説明は後で行います(ただし、非常に簡単です)。


2

Perl、38 41バイト

+1を含める -p

STDINの行に番号を付けます。たとえば、次のように実行します

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

邪悪な正規表現を使用して、二重ループを取得します。

vandermonde.pl

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

2

JavaScript(ES6)、61バイト

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

配列の内包表記(Firefox 30-57)を試してみましたが、5バイト長くなりました。

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

しかし、退屈なネストされたループはおそらく短いでしょう。


1

Haskell、53バイト

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

使用例:f [1,2,4,8,16]-> 20321280

インデックスを経由jしてi、ネストされたループ内でその位置にある要素の差異のリストを作りますjしてi。リスト内のすべての要素の積を作成します。

わずかに長いことが判明した他のバリアント:

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

import Data.List;f i=product[y-x|[x,y]<-subsequences i]、55バイト


1

CJam、16バイト

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

A Simmonsの投稿に応えて、CJamには組み合わせ演算子がありませんが、はい、もっとうまくやることができます:)

@MartinBüttnerのおかげで-1バイト。

オンラインで試す | テストスイート

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バイト

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

誰かがこれをCJamでより良くゴルフできると確信しています。主な問題は、サブセットを取得して、ほとんどのバイトを使い果たす良い方法を見つけることができないことです。これにより、パワーセットが生成され(MartinBüttnerによるアイデアを使用)、長さ2の要素が選択されます。



弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.