Напишите именованную функцию или программу, которая вычисляет произведение кватернионов двух кватернионов. Используйте как можно меньше байтов.
Кватернионы
Кватернионы - это расширение действительных чисел, которое дополнительно расширяет комплексные числа. Вместо одной мнимой единицы i
кватернионы используют три мнимые единицы, i,j,k
которые удовлетворяют отношениям.
i*i = j*j = k*k = -1
i*j = k
j*i = -k
j*k = i
k*j = -i
k*i = j
i*k = -j
(Там также таблицы этих на странице Википедии .)
Словом, каждая мнимая единица возводится в квадрат -1
, а произведение двух разных мнимых единиц является оставшейся третьей единицей в +/-
зависимости от того, (i,j,k)
соблюдается ли циклический порядок (т. Е. Правило правой руки ). Итак, порядок умножения имеет значение.
Общий кватернион - это линейная комбинация действительной части и трех мнимых единиц. Итак, это описывается четырьмя действительными числами (a,b,c,d)
.
x = a + b*i + c*j + d*k
Таким образом, мы можем умножить два кватерниона, используя свойство дистрибутива, стараясь умножить единицы в правильном порядке и сгруппировав одинаковые термины в результате.
(a + b*i + c*j + d*k) * (e + f*i + g*j + h*k)
= (a*e - b*f - c*g - d*h) +
(a*f + b*e + c*h - d*g)*i +
(a*g - b*h + c*e + d*f)*j +
(a*h + b*g - c*f + d*e)*k
С этой точки зрения умножение кватернионов можно рассматривать как карту от пары из 4-х кортежей до одного 4-кортежа, что вам и нужно реализовать.
Формат
Вы должны написать либо программу, либо именованную функцию . Программа должна принимать входные данные из STDIN и распечатывать результат. Функция должна принимать входные данные функции и возвращать (не печатать) выходные данные.
Форматы ввода и вывода являются гибкими. Входные данные представляют собой восемь действительных чисел (коэффициенты для двух кватернионов), а выходные данные состоят из четырех действительных чисел. Входными данными могут быть восемь чисел, два списка из четырех чисел, матрица 2x4 и т. Д. Формат ввода / вывода не должен быть одинаковым. Порядок выбора (1,i,j,k)
коэффициентов зависит от вас.
Коэффициенты могут быть отрицательными или не целыми. Не беспокойтесь о реальной точности или переполнении.
Запрещено: функция или типы специально для кватернионов или эквивалентов.
Контрольные примеры
Они в (1,i,j,k)
формате коэффициента.
[[12, 54, -2, 23], [1, 4, 6, -2]]
[-146, -32, 270, 331]
[[1, 4, 6, -2], [12, 54, -2, 23]]
[-146, 236, -130, -333]
[[3.5, 4.6, -0.24, 0], [2.1, -3, -4.3, -12]]
[20.118, 2.04, 39.646, -62.5]
Реализация эталона
В Python как функция:
#Input quaternions: [a,b,c,d], [e,f,g,h]
#Coeff order: [1,i,j,k]
def mult(a,b,c,d,e,f,g,h):
coeff_1 = a*e-b*f-c*g-d*h
coeff_i = a*f+b*e+c*h-d*g
coeff_j = a*g-b*h+c*e+d*f
coeff_k = a*h+b*g-c*f+d*e
result = [coeff_1, coeff_i, coeff_j, coeff_k]
return result
Питон -
90 75 7269Чистый Python, без библиотек - 90:
Вероятно, довольно сложно сократить это «решение по умолчанию» в Python. Но мне очень любопытно, что могут предложить другие. :)
Использование NumPy -
75 7269:Итак, поскольку ввод и вывод достаточно гибкие, мы можем использовать некоторые функции NumPy и использовать представление скалярного вектора :
Входные аргументы
s
иt
являются скалярными частями двух кватернионов (действительными частями)p
иq
являются соответствующими векторными частями (мнимыми единицами). Вывод представляет собой список, содержащий скалярную часть и векторную часть результирующего кватерниона, причем последний представлен в виде массива NumPy.Простой тестовый скрипт:
(
mult(...)
являясь эталонной реализацией ФП.)Выход:
источник
Хаскелл, 85
Портирование на Haskell экономит нам несколько символов;)
источник
Mathematica
8350Вероятно, можно играть в гольф больше ..
Пробелы и переводы строк не учитываются и не нужны.
Использование:
РЕДАКТИРОВАТЬ Как это работает.
Функция Mathematica
Permutations
делает все возможные перестановки#2
(второй аргумент). Есть 24 перестановок, но нам нужны только{e,f,g,h}
,{f,e,h,g}
,{g,h,e,f}
, и{h,g,f,e}
. Это первая, 8-я, 17-я и 24-я перестановки. Итак, кодточно выбирает их из перестановок второго аргумента и возвращает их в виде матрицы. Но тогда у них пока нет правильного знака. Код
p[{-1,1,-1,1}][[1;;3]]
возвращает матрицу 3x4 с правильным знаком. Мы добавляем его с{1,1,1,1}
помощьюJoin
обычного умножения (Times
или, как в нашем случае, просто записывая их друг за другом) между двумя матрицами, в Mathematica происходит умножение элементов за элементом.Итак, наконец, результат
это матрица
Создание умножения матрицы между
{a,b,c,d}
(первым аргументом#1
) и предыдущей матрицей дает желаемый результат.РЕДАКТИРОВАТЬ 2 более короткий код
Вдохновленный Python-кодом Falko, я разделил кватернион на скалярную и векторную части и использую встроенную команду Mathematica
Cross
для вычисления перекрестного произведения векторных частей:Использование:
источник
1, 8, 17, 24
?Питон, 94
Самый простой способ не слишком длинный.
источник
JavaScript ES6 - 86
источник
Луа - 99
Мог бы также.
Lua "unpack ()" освобождает элементы таблицы. Таким образом, в таблице 'arg' хранятся все входные данные командной строки (включая то,
arg[0]
что является именем файла программы, оно отбрасывается).источник
Python,
5856 символовЯ беру очень либерально использую комнату для маневра в формате ввода / вывода. Входные данные представляют собой 4 комплексных числа, закодированных таким образом:
Он выводит пару комплексных чисел в аналогичном формате, первая из пары кодирует действительное число и
i
часть, вторая кодируетj
иk
части.Чтобы увидеть это работает, обратите внимание, что первый кватернион есть,
x+y*j
а второй естьz+w*j
. Просто оцените(x+y*j)*(z+w*j)
и поймите этоj*t
=conj(t)*j
для любого воображаемого числаt
.источник
i
и какj
действовать как внутренние и внешние сложные коэффициенты. Как увлекательно!(2*w.real-w)
.abs(w)**2/w
будет работать, но за 0. Может быть, даже exec с подстановкой строк будет стоить? `Whispers v2 , 396 байт
Попробуйте онлайн!
Принимает вход в виде
и выводит как
представлятьQ= w + x i + yJ + ZК
Структура дерева этого ответа:
Хорошая часть этого ответа происходит от двух основных недостатков в Whispers:
Поэтому мы можем разбить код на 3 раздела.
Как это устроено
Мы будем использовать следующие определения для ясности и краткости:
Раздел 1. ПерестановкаA и В
Первый раздел является самым длинным и простирается от линии 1 до линии 22 :
Основная цель этого раздела - переставитьВ так что простое поэлементное умножение между A и В возможно. Существует четыре различных вариантаВ умножить элементы A с:
Второй вход,В , хранится в строке 6 . Затем мы разделимВ вниз по центру, как каждое возможное расположение В сгруппированы по парам. Чтобы поменять эти пары (чтобы получить правильные заказы вВ2 и В4 ), мы берем первый и последний элемент, затем объединяем их в обратном порядке:
(формирование[ ф, е ] ) и
(формирование[ ч , г] ). Теперь у нас есть все половинки, необходимые для формирования договоренностей, поэтому мы объединяем их вместе, чтобы сформироватьВ1, Б2, Б3 и В4 , Наконец, мы объединяем эти четыре договоренности вместе, чтобы сформироватьВT , Затем мы быстро сделаемAT , определяется как A повторный 4 раз:
When each element ofBT is multiplied by the corresponding element in AT , we get the (signless) values in q⋅p
Section 2: Signs and products
As said in Section 1, the values inAT and BT correspond to the signless (i.e. positive) values of each of the coefficients in q⋅p . No obvious pattern is found in the signs that would be shorter than simply hardcoding the array, so we hardcode the array:
We'll call this arrayS (signs). Next, we zip together each element in AT,BT and S and take the product of each sub-array e.g. [[a,e,1],[b,f,−1],…,[e,f,−1],[d,e,1]]→D=[ae,−bf,…,−ef,de] .
Section 3: Partitions and final sums.
Once we have the array of coefficients ofq⋅p , with signs, we need to split it into 4 parts (i.e. the four factorised coefficients of q⋅p ), and then take the sums. This leads us to the only golfing opportunity found: moving the
to line 4 rather than 26, as it is used 6 times, each time saving a byte by moving it. Unfortunately, this costs a byte changing the 9 to a 10, so only5 bytes are saved. The next section takes slices of size 4 from the front of D , saving each slice to the corresponding row and passing on the shortened list of D . Once 4 slices are taken, we the take the sum of each, before outputting them all.
источник