Escriba una función o programa con nombre que calcule el producto quaternion de dos cuaterniones. Use la menor cantidad de bytes posible.
Cuaterniones
Los cuaterniones son una extensión de los números reales que amplía aún más los números complejos. En lugar de una sola unidad imaginaria i
, los cuaterniones usan tres unidades imaginarias i,j,k
que satisfacen las relaciones.
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
(También hay tablas de estos en la página de Wikipedia ).
En palabras, cada unidad imaginaria se cuadra con -1
, y el producto de dos unidades imaginarias diferentes es la tercera restante, +/-
dependiendo de si (i,j,k)
se respeta el orden cíclico (es decir, la regla de la mano derecha ). Entonces, el orden de multiplicación es importante.
Un cuaternión general es una combinación lineal de una parte real y las tres unidades imaginarias. Entonces, se describe con cuatro números reales (a,b,c,d)
.
x = a + b*i + c*j + d*k
Entonces, podemos multiplicar dos cuaterniones usando la propiedad distributiva, teniendo cuidado de multiplicar las unidades en el orden correcto y agrupando términos similares en el resultado.
(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
Visto de esta manera, la multiplicación de cuaterniones puede verse como un mapa de un par de 4 tuplas a un solo 4 tuplas, que es lo que se le pide que implemente.
Formato
Debe escribir un programa o una función con nombre . Un programa debe tomar entradas de STDIN e imprimir el resultado. Una función debe tomar entradas de función y devolver (no imprimir) una salida.
Los formatos de entrada y salida son flexibles. La entrada es ocho números reales (los coeficientes para dos cuaterniones), y la salida consta de cuatro números reales. La entrada puede ser ocho números, dos listas de cuatro números, una matriz de 2x4, etc. El formato de entrada / salida no tiene que ser el mismo. El orden de los (1,i,j,k)
coeficientes depende de usted.
Los coeficientes pueden ser negativos o no completos. No se preocupe por la precisión real o los desbordamientos.
Prohibido: función o tipos específicos para cuaterniones o equivalentes.
Casos de prueba
Estos están en (1,i,j,k)
formato de coeficiente.
[[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]
Implementación de referencia
En Python, como función:
#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 7269Python puro, sin bibliotecas - 90:
Probablemente sea bastante difícil acortar esta solución "predeterminada" en Python. Pero tengo mucha curiosidad en cuanto a qué otros podrían llegar. :)
Usando NumPy -
75 7269:Bueno, dado que la entrada y la salida son bastante flexibles, podemos usar algunas funciones NumPy y explotar la representación del vector escalar :
Argumentos de entrada
s
yt
son las partes escalar de los dos cuaterniones (las partes reales) yp
yq
son las partes vector correspondiente (las unidades imaginarias). La salida es una lista que contiene la parte escalar y la parte vectorial del cuaternión resultante, este último representado como una matriz NumPy.Script de prueba simple:
(
mult(...)
siendo la implementación de referencia del OP).Salida:
fuente
Haskell, 85
Portarlo a Haskell nos ahorra algunos caracteres;)
fuente
Mathematica
8350Probablemente se pueda jugar más al golf.
Espacios y líneas nuevas no contados y no necesarios.
Uso:
EDITAR Cómo funciona esto.
La función Mathematica
Permutations
hace todas las permutaciones posibles de#2
(el segundo argumento). Hay 24 permutaciones, pero sólo se necesitan{e,f,g,h}
,{f,e,h,g}
,{g,h,e,f}
, y{h,g,f,e}
. Estas son las permutaciones primera, 8ª, 17ª y 24ª. Entonces el códigolos selecciona exactamente de las permutaciones del segundo argumento y los devuelve como una matriz. Pero aún no tienen la señal correcta. El código
p[{-1,1,-1,1}][[1;;3]]
devuelve una matriz 3x4 con el signo correcto. Lo anteponemos{1,1,1,1}
usandoJoin
, y haciendo una multiplicación normal (Times
o, como es el caso aquí, simplemente escribiéndolos uno después del otro) entre dos matrices hace una multiplicación elemento por elemento en Mathematica.Finalmente, el resultado de
es la matriz
Hacer una matriz de multiplicación entre
{a,b,c,d}
(el primer argumento#1
) y la matriz anterior da el resultado deseado.EDITAR 2 Código más corto
Inspirado por el código Python de Falko, separé el cuaternión en una parte escalar y una parte vectorial, y uso el comando incorporado de Mathematica
Cross
para calcular el producto cruzado de las partes vectoriales:Uso:
fuente
1, 8, 17, 24
?Python, 94
La forma más directa no es demasiado larga.
fuente
JavaScript ES6 - 86
fuente
Lua - 99
Podría también.
El "unpack ()" de Lua libera los elementos de una tabla. Entonces, la tabla 'arg' es donde se almacena toda la entrada de la línea de comandos (incluido
arg[0]
cuál es el nombre del archivo del programa, se descarta).fuente
Python,
5856 caracteresAprovecho muy liberalmente el margen de maniobra del formato de entrada / salida. Las entradas son 4 números complejos, codificados así:
Produce un par de números complejos en un formato similar, el primero del par codifica el real y la
i
parte, el segundo codifica elj
yk
partes .Para ver que esto funciona, tenga en cuenta que el primer cuaternión es
x+y*j
y el segundo esz+w*j
. Solo evalúa(x+y*j)*(z+w*j)
y date cuenta de quej*t
=conj(t)*j
para cualquier número imaginariot
.fuente
i
yj
actúan como coeficientes complejos internos y externos. ¡Que fascinante!(2*w.real-w)
.abs(w)**2/w
funcionaría pero para 0. ¿Quizás valdría la pena incluso un ejecutivo con sustitución de cadena? `Whispers v2 , 396 bytes
Pruébalo en línea!
Toma entrada en el formulario
y salidas como
representarq= w + x i + yj + zk
El árbol de estructura de esta respuesta es:
Una buena parte de esta respuesta proviene de dos fallas principales en Whispers:
Por lo tanto, podemos dividir el código en 3 secciones.
Cómo funciona
Usaremos las siguientes definiciones para claridad y concisión:
Sección 1: PermutandoUN y si
La primera sección es, con mucho, la más larga, desde la línea 1 hasta la línea 22 :
El objetivo principal de esta sección es permutarsi entonces esa simple multiplicación entre elementos UN y si es posible. Hay cuatro arreglos diferentes desi para multiplicar los elementos de UN con:
La segunda entrada,si , se almacena en la línea 6 . Luego nos separamossi en el medio, ya que cada posible arreglo de si se agrupa en pares. Para revertir estos pares (para obtener los pedidos correctos ensi2 y si4 4 ), tomamos el primer y último elemento, luego los concatenamos en orden inverso:
(formando[ f, e ] ) y
(formando[ h , g] ) Ahora tenemos todas las mitades necesarias para formar los arreglos, por lo que los concatenamos juntos para formarsi1, B2, B3 y si4 4 . Finalmente, concatenamos estos cuatro arreglos para formarsiT . Luego hacemos rápidamenteUNT , definido como UN repetido 4 4 veces:
Cuando cada elemento desiT se multiplica por el elemento correspondiente en UNT , obtenemos los valores (sin signo) en q⋅ p
Sección 2: Señales y productos
Como se dijo en la Sección 1, los valores enUNT y siT corresponden a los valores sin signo (es decir, positivos) de cada uno de los coeficientes en q⋅ p . No se encuentra ningún patrón obvio en los signos que serían más cortos que simplemente codificar la matriz, por lo que codificamos la matriz:
Llamaremos a esta matrizS (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.
fuente