Определитель Вандермонде


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два равных элемента в массиве, чтобы проверить, проверяет ли код self-разность ( xi-xi), просто сравнивая с 0.
Рандомра

@randomra Спасибо, я совсем забыл включить один из них. Всякий раз, когда две записи равны, определитель будет равен 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}

Это лямбда-функция, которая принимает вещественный одномерный массив и возвращает число с плавающей запятой или целое число в зависимости от типа ввода. Чтобы вызвать его, назначьте его переменной, затем выполните f.call(input).

Мы получаем все комбинации размера 2 .combination(2)и получаем различия для каждой пары .map {|a, b| b - a}. Мы объединяем полученный массив в строку, разделенную *, затем evalthis, которая возвращает продукт. Если вход имеет длину 1, это будет nilплохо, что в Ruby неверно, поэтому мы можем просто ||1в конце вернуть 1 в этой ситуации. Обратите внимание, что это все еще работает, когда продукт равен 0, потому что по любой причине 0 является правдивым в Ruby.

Проверьте все тестовые примеры онлайн

Сохранено 2 байта благодаря Doorknob!


7

Mathematica, 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 ...
Конор О'Брайен

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

Ой! Это круто.
Конор О'Брайен,

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

@ Nᴮᶻ это может помочь думать о. как собственный знак; таким образом, его можно без пробела принять за другого оператора. Если J не для вас, однако, это понятно.
Конор О'Брайен

4

МАТЛ , 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

Mathematica, 32 байта

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

Я был удивлен, что не нашел встроенного для вещей Вандермонда. Возможно потому, что так легко сделать это самому.

Этот явно конструирует транспонирование ВМ и принимает его определитель (который, конечно, такой же, как и у оригинала). Этот метод оказался значительно короче, чем использование любой формулы, которую я знаю.


3

Haskell, 34 байта

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

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


2

Matlab, 26 байт

(Неконкурирующий)

Простое использование встроенных функций. Обратите внимание, что (еще раз) Matlab's vanderсоздает матрицы Вандермонда, но с измененным порядком строк.

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

2
Почему неконкурентоспособен?
Алекс А.

3
Поскольку я тот, кто сделал этот вызов, я просто хотел предоставить это, чтобы люди могли попробовать свои собственные примеры.
flawr

Разве Det (перевернутые строки) не = (-1) ^ n Det (оригинал)?
hYPotenuser

Я не совсем уверен, так как определитель переключает знак всякий раз, когда вы переключаете два столбца или строки.
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

В ответ на сообщение Симмонса , несмотря на отсутствие в 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.