Encuentra el producto cruzado


20

El producto cruzado de dos vectores tridimensionales y es el vector único tal que:unsiC

  • C es ortogonal a ambos yunsi

  • La magnitud de es igual al área del paralelogramo formado por yCunsi

  • Las direcciones de , y , en ese orden, siguen la regla de la derecha .unsiC

Hay algunas fórmulas equivalentes para productos cruzados, pero una es la siguiente:

un×si=det[yojkun1un2un3si1si2si3]

donde yo , j y k son los vectores unitarios en la primera, segunda y tercera dimensiones.

Desafío

Dados dos vectores 3D, escriba un programa o función completa para encontrar su producto cruzado. Las incorporaciones que calculan específicamente el producto cruzado no están permitidas.

Entrada

Dos matrices de tres números reales cada una. Si su idioma no tiene matrices, los números aún deben agruparse en tres. Ambos vectores tendrán una magnitud <216 . Tenga en cuenta que el producto cruzado no es conmutativo ( a×b=(b×a) ), por lo que debe tener una forma de especificar el orden.

Salida

Su producto cruzado, en un formato razonable, con cada componente con una precisión de cuatro cifras significativas o 104 , lo que sea más flojo. La notación científica es opcional.

Casos de prueba

[3, 1, 4], [1, 5, 9]
[-11, -23, 14]

[5, 0, -3], [-3, -2, -8]
[-6, 49, -10]

[0.95972, 0.25833, 0.22140],[0.93507, -0.80917, -0.99177]
[-0.077054, 1.158846, -1.018133]

[1024.28, -2316.39, 2567.14], [-2290.77, 1941.87, 712.09]
[-6.6345e+06, -6.6101e+06, -3.3173e+06]

Este es el , por lo que gana la solución más corta en bytes.

Maltysen publicó un desafío similar , pero la respuesta fue pobre y la pregunta no fue editada.


¿Se puede tomar la entrada como una matriz 2D?
Dennis

Sí, siempre que 2 sea la dimensión exterior.
lirtosiast

Respuestas:


14

Jalea, 14 13 12 bytes

;"s€2U×¥/ḅ-U

Pruébalo en línea!

Cómo funciona

;"s€2U×¥/ḅ-U Main link. Input: [a1, a2, a3], [b1, b2, b3]

;"           Concatenate each [x1, x2, x3] with itself.
             Yields [a1, a2, a3, a1, a2, a3], [b1, b2, b3, b1, b2, b3].
  s€2        Split each array into pairs.
             Yields [[a1, a2], [a3, a1], [a2, a3]], [[b1, b2], [b3, b1], [b2, b3]].
       ¥     Define a dyadic chain:
     U         Reverse the order of all arrays in the left argument.
      ×        Multiply both arguments, element by element.
        /    Reduce the 2D array of pairs by this chain.
             Reversing yields [a2, a1], [a1, a3], [a3, a2].
             Reducing yields [a2b1, a1b2], [a1b3, a3b1], [a3b2, a2b3].
         ḅ-  Convert each pair from base -1 to integer.
             This yields [a1b2 - a2b1, a3b1 - a1b3, a2b3 - a3b2]
           U Reverse the array.
             This yields [a2b3 - a3b2, a3b1 - a1b3, a1b2 - a2b1] (cross product).

Versión no competitiva (10 bytes)

OK, esto es vergonzoso, pero el lenguaje de manipulación de matriz Jelly no tenía una rotación de matriz incorporada hasta ahora. Con este nuevo incorporado, podemos guardar dos bytes adicionales.

ṙ-×
ç_ç@ṙ-

Esto utiliza el enfoque de la respuesta J de @ AlexA . Pruébalo en línea!

Cómo funciona

ṙ-×     Helper link. Left input: x = [x1, x2, x3]. Right input: y = [y1, y2, y3].

ṙ-      Rotate x 1 unit to the right (actually, -1 units to the left).
        This yields [x3, x1, x2].
  ×     Multiply the result with y.
        This yields [x3y1, x1y2, x2y3].


ç_ç@ṙ-  Main link. Left input: a = [a1, a2, a3]. Right input: b = [b1, b2, b3].

ç       Call the helper link with arguments a and b.
        This yields [a3b1, a1b2, a2b3].
  ç@    Call the helper link with arguments b and a.
        This yields [b3a1, b1a2, b2a3].
_       Subtract the result to the right from the result to the left.
        This yields [a3b1 - a1b3, a1b2 - a2b1, a2b3 - a3b2].
    ṙ-  Rotate the result 1 unit to the right.
        This yields [a2b3 - a3b2, a3b1 - a1b3, a1b2 - a2b1] (cross product).

Convierte cada par de la base -1? Eso es simplemente malvado. +1
ETHproductions

10

LISP, 128 122 bytes

¡Hola! Este es mi código:

(defmacro D(x y)`(list(*(cadr,x)(caddr,y))(*(caddr,x)(car,y))(*(car,x)(cadr,y))))(defun c(a b)(mapcar #'- (D a b)(D b a)))

Sé que no es la solución más corta, pero nadie ha proporcionado una en Lisp, hasta ahora :)

¡Copie y pegue el siguiente código aquí para probarlo!

(defmacro D(x y)`(list(*(cadr,x)(caddr,y))(*(caddr,x)(car,y))(*(car,x)(cadr,y))))(defun c(a b)(mapcar #'- (D a b)(D b a)))

(format T "Inputs: (3 1 4), (1 5 9)~%")
(format T "Result ~S~%~%" (c '(3 1 4) '(1 5 9)))

(format T "Inputs: (5 0 -3), (-3 -2 -8)~%")
(format T "Result ~S~%~%" (c '(5 0 -3) '(-3 -2 -8)))

(format T "Inputs: (0.95972 0.25833 0.22140), (0.93507 -0.80917 -0.99177)~%")
(format T "Result ~S~%" (c '(0.95972 0.25833 0.22140) '(0.93507 -0.80917 -0.99177)))

(format T "Inputs: (1024.28 -2316.39 2567.14), (-2290.77 1941.87 712.09)~%")
(format T "Result ~S~%" (c '(1024.28 -2316.39 2567.14) '(-2290.77 1941.87 712.09)))

Bienvenido a Programming Puzzles y Code Golf Stack Exchange. Esta es una gran respuesta, +1. Bien hecho por responder en un idioma que no va a ganar, pero que sigue jugando mucho. ¡A menudo , los desafíos del código golf son más sobre los idiomas que entre ellos!
wizzwizz4

9

Dyalog APL, 12 bytes

2⌽p⍨-p←⊣×2⌽⊢

Basado en la respuesta J de @ AlexA. y (casualmente) equivalente a la mejora de @ randomra en la sección de comentarios de esa respuesta.

Pruébelo en línea en TryAPL .

Cómo funciona

2⌽p⍨-p←⊣×2⌽⊢  Dyadic function.
              Left argument: a = [a1, a2, a3]. Right argument: b = [b1, b2, b3].

         2⌽⊢  Rotate b 2 units to the left. Yields [b3, b1, b2].
       ⊣×     Multiply the result by a. Yields [a1b3, a2b1, a3b2].
     p←       Save the tacit function to the right (NOT the result) in p.
  p⍨          Apply p to b and a (reversed). Yields [b1a3, b2a1, b3a2].
    -         Subtract the right result (p) from the left one (p⍨).
              This yields [a3b1 - a1b3, a1b2 - a2b1, a2b3 - a3b2].
2⌽            Rotate the result 2 units to the left.
              This yields [a2b3 - a3b2, a3b1 - a1b3, a1b2 - a2b1].

9

J, 27 14 bytes

2|.v~-v=.*2&|.

Este es un verbo diádico que acepta matrices a la izquierda y a la derecha y devuelve su producto cruzado.

Explicación:

         *2&|.     NB. Dyadic verb: Left input * twice-rotated right input
      v=.          NB. Locally assign to v
   v~-             NB. Commute arguments, negate left
2|.                NB. Left rotate twice

Ejemplo:

    f =: 2|.v~-v=.*2&|.
    3 1 4 f 1 5 9
_11 _23 14

Pruébalo aquí

¡Guardado 13 bytes gracias a randomra!


@randomra Eso es genial, ¡gracias! No soy un experto en J, así que todavía estoy descubriendo cómo funciona exactamente, pero tengo una idea general.
Alex A.

Algunas aclaraciones: *2&|.es una bifurcación de dos verbos: *y 2&|.. Multiplica la entrada izquierda por una entrada girada por 2 derecha. Esta bifurcación se almacena de vmodo que cuando escribimos v~, es equivalente a (*2&|.)~, donde ~intercambia los parámetros de entrada izquierdo y derecho para la parte entre paréntesis.
randomra

@randomra Ok, eso tiene sentido. ¡Gracias de nuevo!
Alex A.

6

C, 156 154 150 148 144 bytes

#include <stdio.h>
main(){float v[6];int i=7,j,k;for(;--i;)scanf("%f",v+6-i);for(i=1;i<4;)j=i%3,k=++i%3,printf("%f ",v[j]*v[k+3]-v[k]*v[j+3]);}

No voy a ganar ningún premio por la longitud, pero pensé que tendría una oportunidad de todos modos.

  • La entrada es una lista de componentes delimitados por espacio o nueva línea (es decir, a1 a2 a3 b1 b2 b3), la salida está delimitada por espacios (es decir, c1 c2 c3).
  • Permuta cíclicamente los índices de los dos vectores de entrada para calcular el producto, ¡toma menos caracteres que escribir los determinantes!

Manifestación

Sin golf:

#include <cstdio>
int main()
{
    float v[6];
    int i = 7, j, k;
    for (; --i; ) scanf("%f", v + 6 - 1);
    for (i = 1; i < 4; )
        j = i % 3,
        k = ++i % 3,
        printf("%f ", v[j] * v[k + 3] - v[k] * v[j + 3]);
}

1
Bienvenido a Programming Puzzles y Code Golf Stack Exchange. Esta es una respuesta genial; bien hecho por responder en un idioma que no supere a los idiomas de golf. +1.
wizzwizz4

2
El primero forno necesita{}
eliminado el

saludos, actualizado.
calvinsykes

1
Puede reemplazar & v [6-i] con v + 6-i. Además, puede reemplazar el punto y coma después de j = i% 3 yk = (i + 1)% 3 con comas, lo que hace que todo sea después de una sola declaración para que pueda omitir {}. Finalmente, si inicializa i a 1 para el segundo ciclo for, puede mover el incremento a k = ++ i% 3 guardando un par de paréntesis. Si no le preocupan las advertencias y utiliza la versión correcta de C, también puede omitir la inclusión.
Alchymist

impresionante, salud! Mi compilador no aceptará la omisión del encabezado, por lo que me he quedado con una versión que puedo construir.
calvinsykes

4

Haskell, 41 bytes

x(a,b,c)(d,e,f)=(b*f-c*e,c*d-a*f,a*e-b*d)

Una solución sencilla.


4

Bash + coreutils, 51

eval set {$1}*{$2}
bc<<<"scale=4;$6-$8;$7-$3;$2-$4"
  • La línea 1 construye una expansión de llaves que proporciona el producto cartesiano de los dos vectores y los establece en los parámetros posicionales.
  • La línea 2 resta los términos apropiados; bcrealiza la evaluación aritmética con la precisión requerida.

La entrada es como dos listas separadas por comas en la línea de comandos. Salida como líneas separadas por nueva línea:

$ ./crossprod.sh 0.95972,0.25833,0.22140 0.93507,-0.80917,-0.99177
-.07705
1.15884
-1.01812
$

4

MATL , 17 bytes

!*[6,7,2;8,3,4])d

La primera entrada es a , la segunda es b .

Pruébalo en línea!

Explicación

!              % input b as a row array and transpose into a column array
*              % input a as a row array. Compute 3x3 matrix of pairwise products
[6,7,2;8,3,4]  % 2x3 matrix that picks elements from the former in column-major order
)              % apply index
d              % difference within each column

4

Pyth, 16 bytes

-VF*VM.<VLQ_BMS2

Pruébelo en línea: demostración

Explicación:

-VF*VM.<VLQ_BMS2   Q = input, pair of vectors [u, v]
              S2   creates the list [1, 2]
           _BM     transforms it to [[1, -1], [2, -2]]
      .<VLQ        rotate of the input vectors accordingly to the left:
                   [[u by 1, v by -1], [u by 2, v by -2]]
   *VM             vectorized multiplication for each of the vector-pairs
-VF                vectorized subtraction of the resulting two vectors

3

K5, 44 40 37 32 bytes

Escribí este hace bastante tiempo y lo desempolvé recientemente .

{{x[y]-x[|y]}[*/x@']'3 3\'5 6 1}

En acción:

 cross: {{x[y]-x[|y]}[*/x@']'3 3\'5 6 1};

 cross (3 1 4;1 5 9)
-11 -23 14
 cross (0.95972 0.25833 0.22140;0.93507 -0.80917 -0.99177)
-7.705371e-2 1.158846 -1.018133

Editar 1:

Ahorró 4 bytes al tomar la entrada como una lista de listas en lugar de dos argumentos separados:

old: {m:{*/x@'y}(x;y);{m[x]-m[|x]}'(1 2;2 0;0 1)}
new: {m:{*/x@'y}x    ;{m[x]-m[|x]}'(1 2;2 0;0 1)}

Edición 2:

Ahorró 3 bytes calculando una tabla de búsqueda con decodificación base:

old: {m:{*/x@'y}x;{m[x]-m[|x]}'(1 2;2 0;0 1)}
new: {m:{*/x@'y}x;{m[x]-m[|x]}'3 3\'5 6 1}

Edición 3:

Ahorre 5 bytes reorganizando la aplicación para permitir el uso de una definición tácita en lugar de una lambda local. Desafortunadamente, esta solución ya no funciona en OK, y requiere el intérprete oficial de k5. Voy a tener que tomar mi palabra para esto hasta que arregle el error en OK:

old: {m:{*/x@'y}x;{m[x]-m[|x]}'3 3\'5 6 1}
new: {{x[y]-x[|y]}[*/x@']     '3 3\'5 6 1}

3

Ruby , 49 bytes

->u,v{(0..2).map{|a|u[a-2]*v[a-1]-u[a-1]*v[a-2]}}

Pruébalo en línea!

Volviendo después de 2 años, eliminé 12 bytes usando cómo Ruby trata los índices de matriz negativos. -1es el último elemento de la matriz, -2el segundo último, etc.

Rubí, 57

->u,v{(0..2).map{|a|u[b=(a+1)%3]*v[c=(a+2)%3]-u[c]*v[b]}}

En programa de prueba

f=->u,v{(0..2).map{|a|u[b=(a+1)%3]*v[c=(a+2)%3]-u[c]*v[b]}}

p f[[3, 1, 4], [1, 5, 9]]

p f[[5, 0, -3], [-3, -2, -8]]

p f[[0.95972, 0.25833, 0.22140],[0.93507, -0.80917, -0.99177]]

p f[[1024.28, -2316.39, 2567.14], [-2290.77, 1941.87, 712.09]]

2

Python, 73 48 bytes

Gracias @FryAmTheEggman

lambda (a,b,c),(d,e,f):[b*f-c*e,c*d-a*f,a*e-b*d]

Esto se basa en la definición del componente del producto vectorial cruzado.

Pruébalo aquí


lambda (a,b,c),(d,e,f):...Debería ahorrar mucho.
FryAmTheEggman

@FryAmTheEggman Tienes razón. Olvidé que lambda puede especificar cómo debería ser el argumento.
TanMath

2

Jalea , 5 bytes

[[X1,X2],[y1,y2],[z1,z2]]Z

ṁ4ÆḊƝ

Pruébalo en línea!

Aquí hay una explicación en PDF en caso de que SE Markdown no pueda manejarlo.


El producto cruzado en forma analítica

(X1,y1,z1)v1(X2,y2,z2)v2

v1=X1yo+y1j+z1k
v2=X2yo+y2j+z2k

OXyz

v1×v2=(X1yo+y1j+z1k)×(X2yo+y2j+z2k)

yo×j=k,yo×k=-j,j×yo=-k,j×k=yo,k×yo=j,k×j=-yo

Después de los reordenamientos y cálculos necesarios:

v1×v2=(y1z2-z1y2)yo+(z1X2-X1z2)j+(X1y2-y1X2)k

La estrecha relación con los determinantes de la matriz.

Hay una cosa interesante a tener en cuenta aquí:

X1y2-y1X2=El |X1y1 X2y2El |
z1X2-X1z2=El |z1X1 z2X2El |
y1z2-z1y2=El |y1z1 y2z2El |

El |El |

Explicación del código de gelatina

Bueno ... no hay mucho que explicar aquí. Simplemente genera la matriz:

(X1y1z1X1 X2y2z2X2)

Y para cada par de matrices vecinas, calcula el determinante de la matriz formada al unir las dos.

ṁ4ÆḊƝ – Monadic Link. Takes input as [[x1,x2],[y1,y2],[z1,z2]].
ṁ4    – Mold 4. Cycle the list up to length 4, reusing the elements if necessary.
        Generates [[x1,x2],[y1,y2],[z1,z2],[x1,x2]].
    Ɲ – For each pair of neighbours: [[x1,x2],[y1,y2]], [[y1,y2],[z1,z2]], [[z1,z2],[x1,x2]].
  ÆḊ  – Compute the determinant of those 2 paired together into a single matrix.



1

ES6, 40 bytes

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

44 bytes si la entrada necesita ser dos matrices:

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

52 bytes para una versión más interesante:

(a,b)=>a.map((_,i)=>a[x=++i%3]*b[y=++i%3]-a[y]*b[x])

1

Julia 0.7 , 45 39 bytes

f(a,b)=1:3 .|>i->det([eye(3)[i,:] a b])

Pruébalo en línea!

Utiliza la fórmula basada en determinantes dada en la descripción de la tarea.

Gracias a H.PWiz por -6 bytes.


39 bytes con dos trucos:f(a,b)=1:3 .|>i->det([eye(3)[i,:] a b])
H.PWiz

0

APL (NARS), 23 caracteres, 46 bytes

{((1⌽⍺)×5⌽⍵)-(5⌽⍺)×1⌽⍵}

prueba:

  f←{((1⌽⍺)×5⌽⍵)-(5⌽⍺)×1⌽⍵}
  (3 1 4) f (1 5 9)
¯11 ¯23 14 
  (5 0 ¯3) f (¯3 ¯2 ¯8)
¯6 49 ¯10 
  (0.95972 0.25833 0.22140) f (0.93507 ¯0.80917 ¯0.99177)
¯0.0770537061 1.158846002 ¯1.018133265 
  (1024.28 ¯2316.39 2567.14) f (¯2290.77 1941.87 712.09)
¯6634530.307 ¯6610106.843 ¯3317298.117 

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.