Écrivez une fonction ou un programme nommé qui calcule le produit quaternion de deux quaternions. Utilisez le moins d'octets possible.
Quaternions
Les quaternions sont une extension des nombres réels qui étend encore les nombres complexes. Plutôt qu'une seule unité imaginaire i
, les quaternions utilisent trois unités imaginaires i,j,k
qui satisfont les relations.
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
(Il y a aussi des tableaux de ceux-ci sur la page Wikipedia .)
En d'autres termes, chaque unité imaginaire est au carré -1
, et le produit de deux unités imaginaires différentes est le troisième restant avec un +/-
selon que l'ordre cyclique (i,j,k)
est respecté (c'est -à-dire la règle de droite) ). Donc, l'ordre de multiplication est important.
Un quaternion général est une combinaison linéaire d'une partie réelle et des trois unités imaginaires. Ainsi, il est décrit par quatre nombres réels (a,b,c,d)
.
x = a + b*i + c*j + d*k
Ainsi, nous pouvons multiplier deux quaternions en utilisant la propriété distributive, en prenant soin de multiplier les unités dans le bon ordre et en regroupant les termes similaires dans le résultat.
(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
Vu de cette façon, la multiplication du quaternion peut être considérée comme une carte d'une paire de 4-tuples à un seul 4-tuples, ce que vous êtes invité à mettre en œuvre.
Format
Vous devez écrire un programme ou une fonction nommée . Un programme doit prendre les entrées de STDIN et imprimer le résultat. Une fonction doit accepter les entrées de fonction et retourner (pas imprimer) une sortie.
Les formats d'entrée et de sortie sont flexibles. L'entrée est huit nombres réels (les coefficients pour deux quaternions), et la sortie se compose de quatre nombres réels. L'entrée peut être huit nombres, deux listes de quatre nombres, une matrice 2x4, etc. Le format d'entrée / sortie n'a pas à être le même. L'ordre des (1,i,j,k)
coefficients dépend de vous.
Les coefficients peuvent être négatifs ou non entiers. Ne vous inquiétez pas de la précision réelle ou des débordements.
Interdit: Fonction ou types spécifiquement pour les quaternions ou équivalents.
Cas de test
Celles-ci sont au (1,i,j,k)
format coefficient.
[[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]
Implémentation de référence
En Python, comme fonction:
#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
Python -
90 75 7269Pure Python, pas de bibliothèques - 90:
Il est probablement assez difficile de raccourcir cette solution "par défaut" en Python. Mais je suis très curieux de savoir ce que d'autres pourraient proposer. :)
Utilisation de NumPy -
75 7269:Eh bien, comme l'entrée et la sortie sont plutôt flexibles, nous pouvons utiliser certaines fonctions NumPy et exploiter la représentation scalaire-vectorielle :
Les arguments d'entrée
s
ett
sont les parties scalaires des deux quaternions (les parties réelles) etp
etq
sont les parties vectorielles correspondantes (les unités imaginaires). La sortie est une liste contenant une partie scalaire et une partie vectorielle du quaternion résultant, ce dernier étant représenté par un tableau NumPy.Script de test simple:
(
mult(...)
étant la mise en œuvre de référence du PO.)Production:
la source
Haskell, 85
Le porter sur Haskell nous permet d'économiser quelques caractères;)
la source
Mathematica
8350Peut probablement être joué au golf plus ..
Les espaces et les nouvelles lignes ne comptent pas et ne sont pas nécessaires.
Usage:
EDIT Comment cela fonctionne.
La fonction Mathematica
Permutations
effectue toutes les permutations possibles de#2
(le deuxième argument). Il y a 24 permutations, mais nous avons seulement besoin{e,f,g,h}
,{f,e,h,g}
,{g,h,e,f}
et{h,g,f,e}
. Ce sont les première, 8e, 17e et 24e permutations. Donc, le codeles sélectionne exactement parmi les permutations du deuxième argument et les renvoie sous forme de matrice. Mais ils n'ont pas encore le bon signe. Le code
p[{-1,1,-1,1}][[1;;3]]
renvoie une matrice 3x4 avec le signe correct. Nous le ajoutons{1,1,1,1}
en utilisantJoin
et en faisant une multiplication normale (Times
, ou comme c'est le cas ici en les écrivant juste après l'autre) entre deux matrices, élément par élément dans Mathematica.Alors finalement, le résultat de
est la matrice
Faire une multiplication matricielle entre
{a,b,c,d}
(le premier argument#1
) et l'ancienne matrice donne le résultat souhaité.EDIT 2 Code abrégé
Inspiré par le code Python de Falko, j'ai divisé le quaternion en une partie scalaire et une partie vectorielle, et j'utilise la commande intégrée de Mathematica
Cross
pour calculer le produit croisé des parties vectorielles:Usage:
la source
1, 8, 17, 24
?Python, 94
La manière la plus simple n'est pas trop longue.
la source
JavaScript ES6 - 86
la source
Lua - 99
Peut-être aussi.
Le "unpack ()" de Lua libère les éléments d'une table. Ainsi, la table 'arg' est l'endroit où toutes les entrées de ligne de commande sont stockées (y compris
arg[0]
le nom de fichier du programme, il est supprimé).la source
Python,
5856 caractèresJe prends une utilisation très libérale de la marge de manœuvre du format d'entrée / sortie. Les entrées sont 4 nombres complexes, codés ainsi:
Il génère une paire de nombres complexes dans un format similaire, le premier de la paire code le réel et la
i
partie, le second code lej
et lesk
parties.Pour voir cela fonctionne, notez que le premier quaternion est
x+y*j
et le second estz+w*j
. Il suffit d'évaluer(x+y*j)*(z+w*j)
et de réaliser quej*t
=conj(t)*j
pour tout nombre imaginairet
.la source
i
etj
agissez comme des coefficients complexes internes et externes. Comme c'est fascinant!(2*w.real-w)
.abs(w)**2/w
fonctionnerait mais pour 0. Peut-être que même un exécutable avec substitution de chaîne en vaudrait la peine? `Whispers v2 , 396 octets
Essayez-le en ligne!
Prend entrée dans le formulaire
et sorties comme
représenterq= w + x i + yj + zk
L'arbre de structure de cette réponse est:
Une bonne partie de cette réponse provient de deux défauts principaux dans Whispers:
Par conséquent, nous pouvons diviser le code en 3 sections.
Comment ça fonctionne
Nous utiliserons les définitions suivantes pour plus de clarté et de concision:
Section 1: PermutingA and B
The first section is by far the longest, stretching from line 1 to line 22:
The main purpose of this section is to permuteB so that simple element-wise multiplication between A and B is possible. There are four different arrangements of B to multiply the elements of A with:
The second input,B , is stored on line 6. We then split B down the middle, as each possible arrangement of B is grouped in pairs. In order to reverse these pairs (to get the correct orders in B2 and B4 ), we take the first and last element, then concatenate them in reverse order:
(forming[f,e] ) and
(forming[h,g] ). We now have all the halves needed to form the arrangements, so we concatenate them together to form B1,B2,B3 and B4 . Finally, we concatenate these four arrangements together to form BT . We then quickly make AT , defined as A repeated 4 times:
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.
la source