Детермінант Вандермонд


25

Даний вектор nзначень (x1,x2,x3,...,xn)повертає визначник відповідної матриці Вандермондза .

Цей визначник можна записати так:

формула

Деталі

Ваша програма / функція повинна приймати список номерів з плаваючою комою у будь-якому зручному форматі, що дозволяє змінювати довжину, та виводити вказаний визначник.

Можна припустити, що введення та вихід знаходяться в межах значень, які підтримує ваша мова. Якщо ви не підтримуєте числа з плаваючою комою, ви можете вважати цілі числа.

Деякі тестові випадки

Зауважте, що щоразу, коли є два рівні записи, визначником буде те 0, що є два рівні рядки у відповідній матриці Вандермонде. Дякуємо @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 Ні, дивіться перший тестовий випадок.
Алекс А.

3
Важливий тестовий випадок: [1,2,2,3] => 0два рівні елементи в масиві, щоб перевірити, чи код перевіряє самовідмінність ( xi-xi) лише порівнянням з 0.
випадкова

@randomra Дякую, я зовсім забув включити один із них. Щоразу, коли дві записи рівні, визначником буде 0, оскільки є два рази в одному рядку.
flawr

1
@flawr Очікуваний результат був зрозумілий з ваших специфікацій. Я запропонував тестовий випадок, щоб відповіді, не підготовлені для рівних цифр, могли легше знайти свої помилки.
randomra

Відповіді:


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}

Це лямбда-функція, яка приймає дійсний значення, одновимірний масив і повертає поплавок або ціле число залежно від типу введення. Щоб викликати його, призначте його змінній, а потім зробіть f.call(input).

Ми отримуємо всі комбінації розміру 2 за допомогою .combination(2)та отримуємо різниці для кожної пари, що використовує .map {|a, b| b - a}. Ми з'єднуємо отриманий масив у рядок, розділений на *, потім evalце, що повертає добуток. Якщо вхід має довжину 1, це буде nilфальси в Рубі, тож ми можемо лише ||1в кінці повернути 1 у цій ситуації. Зауважте, що це все ще працює, коли продукт дорівнює 0, тому що з будь-якої причини 0 Ruby в Ruby.

Перевірте всі тестові випадки в Інтернеті

Збережено 2 байти завдяки Doorknob!


7

Математика, 30 байт

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

Це анонімна функція.

Розширений Mathematica, він еквівалентний (1 ##1 & ) @@ Apply[#2 - #1 & , Subsets[#1, {2}], {1}] &. 1##&є еквівалентом для Times(подяки на сторінці порад), який застосовується до кожної окремої пари елементів зі списку вводу, породженої Subsets[list, {2}]. Зверніть увагу, що Subsetsне перевіряється на унікальність елементів.


5

J, 13 байт

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

Це монадійна функція, яка приймає масив і повертає число. Використовуйте його так:

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

Пояснення

Я явно будую матрицю Вандермонд, пов'язану з вхідним масивом, а потім обчислюю її визначник.

-/ .*@(^/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 ...
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Детермінант - це особливий випадок, який потребує роздільного простору, оскільки .також є символом модифікатора. Те саме для :себе.
Згарб

Ой! Круто.
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Власне, я думаю, що саме це робить J uncool. J означає Jot, тобто крапку або маленьке кільце (APL's ), як в роботі з J ... Неймовірно перевантажений .і :(що знову ж таки візуально такий же, як два складених .s) робить J важким для читання (для мене). Наскільки більше, коли пробіли поруч із крапками визначають значення! J - х .повинна бути самим перевантаженим символом у всіх обчислювальну історії: я вважаю 53 різного значення .і 43 (61 , якщо вважати всі _9:в 9:) різні значення :. Юкк. ;-)
Адам

@ Nᴮᶻ це може допомогти придумати. як власний знак; таким чином, без пробілу можна помилитися з іншим оператором. Однак якщо J не для вас, це зрозуміло.
Conor O'Brien

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 ... Я написав це сам, намагаючись перемогти Jelly: P
FryAmTheEggman

@FryAmTheEggman Awww. Ти правий. Дякую за голову!
Луїс Мендо

Так, я зрозумів, що це проблема. Я б подумав спробувати щось на зразок додавання обгортки, коли ви Xnхочете зробити чек, як- if size(arg) == [1,1] ...небудь. Я занадто лінивий, щоб переглянути джерело, але (сподіваюся) це не повинно бути таким складним.
FryAmTheEggman

@FryAmTheEggman Насправді я не впевнений, що це проблема (саме тому я швидко відредагував свій коментар). Якщо перший вхід є числом, то другий вхід повинен бути 1або 0тоді він не має значення, якщо перший вхід інтерпретується як масив або як число. Справжня проблема полягає в тому, що другий вхід не може перевищувати розмір масиву. Msgstr "Скільки способів вибрати 2 елемента з 1 елемента". У цьому випадку значення різниці масивів / чисел має значення: якщо перший вхід - це повернення масиву [](порожній масив), якщо це повернення числа 0. Гадаю, я повернусь [], бо тоді pзмушує інше тлумачення
Луїс Мендо

@FryAmTheEggman Я думаю, що я розділю функцію на дві версії. Знову дякую!
Луїс Мендо

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)

Дякуємо @FryAmTheEggman та @ Pietu1998 за кожен байт!


1
* F у порожньому масиві дійсно має бути 1.
lirtosiast

3

Математика, 32 байти

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

Я був здивований, що не знайшов вбудованого матеріалу для Vandermonde. Можливо, тому, що так легко зробити це самому.

Цей явно будує транспонінг VM та приймає його детермінант (що, звичайно, є таким же, як оригінал). Цей метод виявився значно коротшим, ніж використання будь-якої мені відомої формули.


3

Хаскелл, 34 байти

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

Рекурсивне рішення. Коли новий елемент hє попередньо випередженим, вираз множать на добуток x-hдля кожного елемента xсписку. Завдяки Згарбу за 1 байт.


2

Матлаб, 26 байт

(неконкурентоспроможний)

Безпосереднє використання вбудованих. Зауважте, що (вкотре) Matlab's vanderстворює матриці Vandermonde, але з черговістю рядків.

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

2
Чому неконкуренто?
Олексій А.

3
Оскільки я є тим, хто зробив цей виклик, я просто хотів надати це, щоб люди могли спробувати власні приклади.
flawr

Чи не Дет (перевернуті рядки) = (-1) ^ n Дет (оригінал)?
hYPotenuser

Я не зовсім впевнений, як детермінанти перемикаються на знак кожного разу, коли ви перемикаєте два стовпці чи рядки.
недолік

@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

У відповідь на повідомлення Сіммонса , незважаючи на відсутність у CJam оператора комбінацій, так, можна зробити краще :)

-1 байт завдяки @ MartinBüttner.

Спробуйте в Інтернеті | Тестовий набір

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 ... Основне питання полягає в тому, що я не бачу хорошого способу отримання підмножини, що використовує більшість моїх байтів. Це генерує набір потужності (використовуючи ідею Мартіна Бюттнера), а потім вибирає елементи довжиною-2.



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.