Kuaterniyonları Çarpma


13

İki quaternionun quaternion ürününü hesaplayan adlandırılmış bir işlev veya program yazın. Mümkün olduğunca az bayt kullanın.

Kuaterniyonlar

Kuaterniyonlar , karmaşık sayıları daha da genişleten gerçek sayıların bir uzantısıdır. iKuaterniyonlar, tek bir hayali birimden ziyade i,j,kilişkileri tatmin eden üç hayali birim kullanırlar .

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

( Wikipedia sayfasında bunların tabloları da vardır .)

Kelimelerle, her hayali birim kareler -1ve iki farklı hayali birimin çarpımı +/-, döngüsel düzene uyulup (i,j,k)uyulmadığına (yani sağ-kural ) bağlı olarak kalan üçüncü birimdir . Bu nedenle, çarpma sırası önemlidir.

Genel bir kuaterniyon, gerçek bir parçanın ve üç hayali birimin doğrusal bir kombinasyonudur. Yani, dört gerçek sayı ile tanımlanır (a,b,c,d).

x = a + b*i + c*j + d*k

Böylece, dağıtım özelliğini kullanarak iki dördüncüyü çoğaltabiliriz, birimleri doğru sırayla çarpmaya dikkat edebilir ve sonuçtaki terimler gibi gruplayabiliriz.

(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

Bu şekilde görüldüğü gibi, kuaterniyon çarpımı, bir çift 4-tuple'den tek bir 4-tuple'ye bir harita olarak görülebilir;

Biçim

Bir program veya adlandırılmış işlev yazmalısınız . Bir program STDIN'den girdi almalı ve sonucu yazdırmalıdır. Bir işlev, işlev girişlerini almalı ve bir çıktı döndürmelidir (yazdırmaz).

Giriş ve çıkış formatları esnektir. Girdi sekiz gerçek sayıdır (iki kuaterniyon için katsayılar) ve çıktı dört gerçek sayıdan oluşur. Giriş sekiz sayı, dört sayıdan oluşan iki liste, 2x4 matris vb. Olabilir. Giriş / çıkış formatı aynı olmak zorunda değildir. Katsayıların sırası (1,i,j,k)size kalmış.

Katsayılar negatif olabilir veya bütün olmayabilir. Gerçek hassasiyet veya taşmalar hakkında endişelenmeyin.

Yasaklı: Özellikle kuaterniyonlar veya eşdeğerleri için işlev veya türler.

Test senaryoları

Bunlar (1,i,j,k)katsayı biçimindedir.

[[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]

Referans uygulaması

Python'da, işlev olarak:

#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

Yanıtlar:


4

CJam, 49 45 39 bayt

"cM-^\M-^G-^^KM-zP"256bGbq~m*f{=:*}4/{:-W*}/W*]`

Yukarıdaki kod, yazdırılamayan karakterler içerdiğinden, düzeltme ve M gösterimini kullanır.

İki ek bayt pahasına, bu karakterlerden kaçınılabilir:

6Z9C8 7YDXE4BFA5U]q~m*f{=:*}4/{:-W*}/W*]`

Bu sürümü çevrimiçi deneyebilirsiniz: CJam tercüman

Test senaryoları

Hesaplamak (a + bi + cj + dk) * (e + fi + gj + hk)için aşağıdaki girişi kullanın:

[ d c b a ] [ h g f e ]

Çıktı

[ z y x w ]

ki bu kuaterniyona karşılık gelir w + xi + yj + zk.

$ base64 -d > product.cjam <<< ImOchy0eS/pQIjI1NmJHYnF+bSpmez06Kn00L3s6LVcqfS9XKl1g
$ wc -c product.cjam
39 product.cjam
$ LANG=en_US cjam product.cjam <<< "[23 -2 54 12] [-2 6 4 1]"; echo
[331 270 -32 -146]
$ LANG=en_US cjam product.cjam <<< "[-2 6 4 1] [23 -2 54 12]"; echo
[-333 -130 236 -146]
$ LANG=en_US cjam product.cjam <<< "[0 -0.24 4.6 3.5] [-12 -4.3 -3 2.1]"; echo
[-62.5 39.646 2.04 20.118]

Nasıl çalışır

6Z9C8 7YDXE4BFA5U]  " Push the array [ 6 3 9 12 8 7 2 13 1 14 4 11 15 10 5 0].         ";
q~                  " Read from STDIN and interpret the input.                         ";
m*                  " Compute the cartesian product of the input arrays.               ";
f                   " Execute the following for each element of the first array:       ";
{                   " Push the cartesian product (implicit).                           ";
    =               " Retrieve the corresponding pair of coefficients.                 ";
    :*              " Calculate their product.                                         ";
}                   "                                                                  ";
4/                  " Split into chunks of 4 elements.                                 ";
{:-W*}/             " For each, subtract the first element from the sum of the others. ";
W*                  " Multiply the last integers (coefficient of 1) by -1.             ";
]`                  " Collect the results into an array and stringify it.              ";

6

Python (83)

r=lambda A,B,R=range(4):[sum(A[m]*B[m^p]*(-1)**(14672>>p+4*m)for m in R)for p in R]

İki listeyi Alır A,Biçinde [1,i,j,k]düzen ve aynı biçimde bir sonuç döndürür.

Ana fikir, [1,i,j,k]endekslere karşılık [0,1,2,3]geldiğinde, endeksleri XOR'layarak ürünün endeksini (imzalamak) elde etmenizdir. Yani, endekse konan terimler pXOR'u endeksleyenler pve dolayısıyla ürünlerdir A[m]*B[m^p].

Sadece işaretlerin çözülmesi için kalır. Bulduğum en kısa yol, onları sihirli bir dizgiye kodlamaktı. 16 olasılık (m,p)sayılar dönüştürülüyor 0için 15olduğu gibi p+4*m. İkili sayı 14672, işaretlere ihtiyaç duyulan 1yerlerde bulunur -1. Uygun yer sayısını değiştirerek , son basamakta a 1veya 0rüzgâr yukarı doğru kaydırarak , sayıyı tek veya çift yapar ve böylece (-1)**ya 1da -1gerektiği gibi olur.


XOR kısmı saf dahidir.
Dennis

3

Python - 90 75 72 69

Saf Python, kütüphane yok - 90:

m=lambda a,b,c,d,e,f,g,h:[a*e-b*f-c*g-d*h,a*f+b*e+c*h-d*g,a*g-b*h+c*e+d*f,a*h+b*g-c*f+d*e]

Python'daki bu "varsayılan" çözümü kısaltmak muhtemelen oldukça zordur. Ama başkalarının neler yapabileceğini merak ediyorum. :)


NumPy - 75 72 69 Kullanma :

Giriş ve çıkış oldukça esnek olduğundan, bazı NumPy işlevlerini kullanabilir ve skaler vektör sunumundan yararlanabiliriz :

import numpy
m=lambda s,p,t,q:[s*t-sum(p*q),s*q+t*p+numpy.cross(p,q)]

Girdi argümanları sve tiki kuaterniyonun skaler kısımları (gerçek kısımlar) ve pve qkarşılık gelen vektör kısımlarıdır (hayali birimler). Çıktı, elde edilen kuaterniyonun skaler kısmını ve vektör kısmını içeren bir listedir; ikincisi NumPy dizisi olarak temsil edilir.

Basit test komut dosyası:

for i in range(5):
    a,b,c,d,e,f,g,h=np.random.randn(8)
    s,p,t,q=a, np.array([b, c, d]), e, np.array([f, g, h])
    print mult(a, b, c, d, e, f, g, h), "\n", m(s,p,t,q)

( mult(...)OP'nin referans uygulamasıdır.)

Çıktı:

[1.1564241702553644, 0.51859264077125156, 2.5839001110572792, 1.2010364098925583] 
[1.1564241702553644, array([ 0.51859264,  2.58390011,  1.20103641])]
[-1.8892934508324888, 1.5690229769129256, 3.5520713781125863, 1.455726589916204] 
[-1.889293450832489, array([ 1.56902298,  3.55207138,  1.45572659])]
[-0.72875976923685226, -0.69631848934167684, 0.77897519489219036, 1.4024428845608419] 
[-0.72875976923685226, array([-0.69631849,  0.77897519,  1.40244288])]
[-0.83690812141836401, -6.5476014589535243, 0.29693969165495304, 1.7810682337361325] 
[-0.8369081214183639, array([-6.54760146,  0.29693969,  1.78106823])]
[-1.1284033842268242, 1.4038096725834259, -0.12599103441714574, -0.5233468317643214] 
[-1.1284033842268244, array([ 1.40380967, -0.12599103, -0.52334683])]

2

Haskell, 85

m a b c d e f g h=[a*e-b*f-c*g-d*h,a*f+b*e+c*h-d*g,a*g-b*h+c*e+d*f,a*h+b*g-c*f+d*e]

Haskell'e taşımak bize birkaç karakter kazandırıyor;)


2

Mathematica 83 50

Muhtemelen daha fazla golf yapılabilir ..

p = Permutations;
f = #1.(Join[{{1, 1, 1, 1}}, p[{-1, 1, -1, 1}][[1 ;; 3]]] p[#2][[{1, 8, 17, 24}]]) &

Alanlar ve yeni satırlar sayılmaz ve gerekli değildir.

Kullanımı:

f[{a,b,c,d},{e,f,g,h}]        (* => {x,w,y,z}   *)


EDIT Bu nasıl çalışır?

Mathematica işlevi Permutationstüm olası permütasyonları yapar #2(ikinci argüman). Orada 24 permütasyon vardır, ama biz sadece ihtiyaç {e,f,g,h}, {f,e,h,g}, {g,h,e,f}, ve {h,g,f,e}. Bunlar ilk, 8, 17 ve 24. permütasyonlardır. Yani kod

p[#2][[{1,8,17,24}]]

bunları ikinci argümanın permütasyonlarından tam olarak seçer ve bunları bir matris olarak döndürür. Ama sonra henüz doğru işarete sahip değiller. Kod p[{-1,1,-1,1}][[1;;3]], doğru işaretli bir 3x4 matrisi döndürür. Bunu {1,1,1,1}kullanarak Joinve Timesiki matris arasında normal bir çarpma yaparak ( ya da sadece birbiri ardına yazarak olduğu gibi) bunu Mathematica'da elemanlar arası çarpma yaparız.

Sonunda, sonucu

(Join[{{1, 1, 1, 1}}, p[{-1, 1, -1, 1}][[1 ;; 3]]] p[#2][[{1, 8, 17, 24}]])

matris mi

 e  f  g  h
-f  e -h  g
-g  h  e -f
-h -g  f  e

{a,b,c,d}(İlk argüman #1) ile eski matris arasında bir matris çarpımı yapmak istenen sonucu verir.



EDIT 2 Daha kısa kod

Falko'nun Python kodundan esinlenerek, bir skaleri ve bir vektör parçasında kuaterniyonu ayırdım ve Crossvektör parçalarının çapraz ürününü hesaplamak için Mathematica'nın yerleşik komutunu kullanıyorum:

f[a_, A_, b_, B_] := Join[{a*b - A.B}, a*B + b*A + Cross[A, B]]

Kullanımı:

f[a,{b,c,d},e,{f,g,h}]        (* => {x,w,y,z}   *)

Bunun nasıl çalıştığını açıklayabilir misiniz? Nedir 1, 8, 17, 24?
xnor

1

Python, 94

En basit yol çok uzun değil.

def m(a,b,c,d,e,f,g,h):return[a*e-b*f-c*g-d*h,a*f+b*e+c*h-d*g,a*g-b*h+c*e+d*f,a*h+b*g-c*f+d*e]

1

JavaScript ES6 - 86

f=(a,b,c,d,e,f,g,h)=>[a*e-b*f-c*g-d*h,a*f+b*e+c*h-d*g,a*g-b*h+c*e+d*f,a*h+b*g-c*f+d*e]

1

Lua - 99

Belki de.

_,a,b,c,d,e,f,g,h=unpack(arg)print(a*e-b*f-c*g-d*h,a*f+b*e+c*h-d*g,a*g-b*h+c*e+d*f,a*h+b*g-c*f+d*e)

Lua'nın "unpack ()" tablonun elemanlarını serbest bırakır. Böylece 'arg' tablosu tüm komut satırı girişlerinin depolandığı yerdir ( arg[0]programın dosya adı da dahil olmak üzere atılır).


1

Python, 58 56 karakter

m=lambda x,y,z,w:(x*z-y*(2*w.real-w),x*w+y*(2*z.real-z))

Attığım çok giriş / çıkış biçimi kıpırdatmak oda liberal kullanımını. Girişler, bu şekilde kodlanan 4 karmaşık sayıdır:

x = a+b*i
y = c+d*i
z = e+f*i
w = g+h*i

Benzer bir formatta bir çift karmaşık sayı çıkarır, çiftin birincisi gerçek ve iparçayı, ikincisi jve kparçaları kodlar .

Bunun işe yaradığını görmek için ilk dördüncülüğün x+y*jikincisi olduğunu unutmayın z+w*j. Sadece herhangi bir hayali sayı için (x+y*j)*(z+w*j)bu j*t= değerini değerlendirin .conj(t)*jt


Çok zeki! Kuaterniyonların neden ifadenizden göründüğü gibi karmaşık sayılarla karmaşık sayılar gibi çoğaldığını biliyor musunuz?
xnor

Boşver, şimdi açıklama nasıl anladığımız ive jiç ve dış kompleks katsayıları olarak gibi hareket ederler. Ne kadar hayranlık verici!
xnor

Bağlam aramalarının karakterlerinizin 2 / 5'inden fazlasını alması komik. Her birini kullanarak bir tıraş olabilir düşünüyorum (2*w.real-w). abs(w)**2/wçalışabilir ama 0 için. Belki string yerine oyuncu ile yürütmek bile buna değer olurdu? `
XNOR

1

Fısıltılar v2 , 396 bayt

> 1
> 2
> 0
> 4
> Input
> Input
>> 6ᶠ2
>> 6ᵗ2
>> 7ⁿ3
>> 7ⁿ1
>> 10‖9
>> 8ⁿ3
>> 8ⁿ1
>> 13‖12
>> 7‖8
>> 11‖14
>> 8‖7
>> 14‖11
>> 15‖16
>> 19‖17
>> 20‖18
>> 4⋅5
>> L⋅R
>> Each 23 22 21
> [1,-1,-1,-1,1,1,1,-1,1,-1,1,1,1,1,-1,1]
>> Each 23 24 25
>> 26ᶠ4
>> 26ᵗ4
>> 28ᶠ4
> 8
>> 26ᵗ30
>> 31ᶠ4
>> 31ᵗ4
>> ∑27
>> ∑29
>> ∑32
>> ∑33
>> Output 34 35 36 37

Çevrimiçi deneyin!

Formda girdi alır

[a, b, c, d]
[e, f, g, h]

ve çıktılar

w
x
y
z

temsil etmek üzereq=w+xi+yj+zk

Bu cevabın yapı ağacı:

ağaç

Bu cevabın iyi bir kısmı Whispers'daki iki ana hatadan geliyor:

  • Bir diziyi tersine çevirecek işlev yok
  • Kartezyen ürünün hesaplanmasında setlerin kullanımı

Bu nedenle, kodu 3 bölüme ayırabiliriz.

Nasıl çalışır

Açıklık ve kısalık için aşağıdaki tanımları kullanacağız:

q=a+bi+cj+dk
p=e+fi+gj+hk
r=w+xi+yj+zk,(qp=r)
A=[a,b,c,d]
B=[e,f,g,h]
C=[w,x,y,z]

Bölüm 1: veAB

İlk bölüm, satır 1'den satır 22'ye kadar uzanan en uzun bölümdür :

> 1
> 2
> 0
> 4
> Input
> Input
>> 6ᶠ2
>> 6ᵗ2
>> 7ⁿ3
>> 7ⁿ1
>> 10‖9
>> 8ⁿ3
>> 8ⁿ1
>> 13‖12
>> 7‖8
>> 11‖14
>> 8‖7
>> 14‖11
>> 15‖16
>> 19‖17
>> 20‖18
>> 4⋅5

Bu bölümün temel amacı böylece ve arasında basit eleman-bazlı çarpma mümkündür. elemanlarını çoğaltmak için dört farklı düzenlemesi vardır:BABBA

B1=[e,f,g,h]
B2=[f,e,h,g]
B3=[g,h,e,f]
B4=[h,g,f,e]

İkinci giriş, , 6. hatta kaydedilir . Daha sonra ortada böldük, çünkü her olası düzenlemesi çiftler halinde gruplandırıldı. Bu çiftleri tersine çevirmek için ( ve doğru siparişleri almak için ), ilk ve son öğeyi alır, ardından bunları ters sırada birleştiririz:BB B B 2 B 4BBB2B4

>> 7ⁿ3
>> 7ⁿ1
>> 10‖9

( ) ve[f,e]

>> 8ⁿ3
>> 8ⁿ1
>> 13‖12

[h,g]B1,B2,B3B4BTATA4

AT=[a,b,c,d,a,b,c,d,a,b,c,d,a,b,c,d]
BT=[e,f,g,h,f,e,h,g,g,h,e,f,h,g,f,e]

BTATqp

Bölüm 2: İşaretler ve ürünler

ATBTqp

> [1,-1,-1,-1,1,1,1,-1,1,-1,1,1,1,1,-1,1]

SAT,BTS[[a,e,1],[b,f,1],,[e,f,1],[d,e,1]]D=[ae,bf,,ef,de]

Bölüm 3: Bölümler ve nihai toplamlar.

qpqp

> 4

54DD

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.