Trouver le produit croisé

20

Le produit croisé de deux vecteurs tridimensionnels et est le vecteur unique tel que:abc

  • ca b est orthogonal à etab

  • La magnitude de est égale à l'aire du parallélogramme formé par etcab

  • Les directions de , et , dans cet ordre, suivent la règle de droite .abc

Il existe quelques formules équivalentes pour les produits croisés, mais l'une est la suivante:

a×b=det[ijka1a2a3b1b2b3]

i , j et k sont les vecteurs unitaires dans les première, deuxième et troisième dimensions.

Défi

Étant donné deux vecteurs 3D, écrivez un programme ou une fonction complète pour trouver leur produit croisé. Les fonctions intégrées qui calculent spécifiquement le produit croisé ne sont pas autorisées.

Contribution

Deux tableaux de trois nombres réels chacun. Si votre langue n'a pas de tableaux, les numéros doivent toujours être regroupés en trois. Les deux vecteurs auront une magnitude <216 . Notez que le produit croisé n'est pas commutatif ( a×b=(b×a) ), vous devriez donc avoir un moyen de spécifier l'ordre.

Production

Leur produit croisé, dans un format raisonnable, avec chaque composant précis à quatre chiffres significatifs ou 104 , selon le plus lâche. La notation scientifique est facultative.

Cas de test

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

C'est le , donc la solution la plus courte en octets l'emporte.

Maltysen a affiché un défi similaire , mais la réponse a été médiocre et la question n'a pas été modifiée.

lirtosiast
la source
L'entrée peut-elle être prise comme un tableau 2D?
Dennis
Oui, tant que 2 est la dimension extérieure.
lirtosiast

Réponses:

14

Gelée, 14 13 12 octets

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

Essayez-le en ligne!

Comment ça fonctionne

;"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).

Version non concurrente (10 octets)

OK, c'est embarrassant, mais le langage de manipulation de tableau Jelly n'avait pas de fonction intégrée pour la rotation du tableau jusqu'à présent. Avec ce nouveau intégré, nous pouvons économiser deux octets supplémentaires.

ṙ-×
ç_ç@ṙ-

Cela utilise l'approche de la réponse J de @ AlexA . Essayez-le en ligne!

Comment ça fonctionne

ṙ-×     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).
Dennis
la source
Convertir chaque paire de la base -1? C'est juste mal. +1
ETHproductions
10

LISP, 128 122 octets

Salut! Voici mon code:

(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)))

Je sais que ce n'est pas la solution la plus courte, mais personne n'en a fourni une à Lisp jusqu'à présent :)

Copiez et collez le code suivant ici pour l'essayer!

(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)))
PieCot
la source
Bienvenue dans Programming Puzzles et Code Golf Stack Exchange. C'est une excellente réponse, +1. Bravo pour avoir répondu dans une langue qui ne gagnera pas, mais tout en jouant au golf. Souvent, les défis de code-golf concernent davantage les langues qu'entre elles!
wizzwizz4
9

Dyalog APL, 12 octets

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

Basé sur la réponse J de @ AlexA. Et (par coïncidence) équivalent à l'amélioration de @ randomra dans la section commentaire de cette réponse.

Essayez-le en ligne sur TryAPL .

Comment ça fonctionne

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].
Dennis
la source
9

J, 27 14 octets

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

Il s'agit d'un verbe dyadique qui accepte les tableaux à gauche et à droite et renvoie leur produit croisé.

Explication:

         *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

Exemple:

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

Essayez-le ici

13 octets enregistrés grâce à randomra!

Alex A.
la source
@randomra C'est génial, merci! Je ne suis pas un expert en J, je cherche toujours à savoir comment cela fonctionne, mais j'ai une idée générale.
Alex A.
Quelques clarifications: *2&|.est une fourchette de deux verbes: *et 2&|.. Il multiplie l'entrée gauche par une entrée pivotée de 2 droite. Cette fourchette est stockée dans vdonc lorsque nous écrivons v~, elle est équivalente à (*2&|.)~, où les ~échanges les paramètres d'entrée gauche et droite pour la partie entre parenthèses.
randomra
@randomra D'accord, cela a du sens. Merci encore!
Alex A.
6

C, 156 154 150 148 148 144 octets

#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]);}

Je ne gagnerai aucun prix pour la durée, mais j'ai pensé que j'aurais quand même un essai.

  • L'entrée est une liste de composants séparés par une nouvelle ligne ou un espace (c.-à-d. A1 a2 a3 b1 b2 b3), la sortie est délimitée par un espace (c.-à-d. C1 c2 c3).
  • Permute cycliquement les indices des deux vecteurs d'entrée pour calculer le produit - prend moins de caractères que d'écrire les déterminants!

Démo

Non 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]);
}
calvinsykes
la source
1
Bienvenue dans Programming Puzzles et Code Golf Stack Exchange. C'est une excellente réponse; bravo pour répondre dans une langue qui ne battra pas les langues du golf. +1.
wizzwizz4
2
Votre premier forn'a pas besoin{}
supprimé le
cheers, mis à jour.
calvinsykes
1
Vous pouvez remplacer & v [6-i] par v + 6-i. En outre, vous pouvez remplacer le point-virgule après j = i% 3 et k = (i + 1)% 3 par des virgules, ce qui fait tout après la pour une seule instruction afin que vous puissiez omettre le {}. Enfin, si vous initialisez i à 1 pour la seconde boucle for, vous pouvez déplacer l'incrément vers k = ++ i% 3 en économisant quelques crochets. Si vous n'êtes pas préoccupé par les avertissements et utilisez la bonne version de C, vous pouvez également ignorer l'inclusion.
Alchymist
génial, bravo! Mon compilateur n'acceptera pas l'omission de l'en-tête, donc je suis resté avec une version que je suis capable de construire.
calvinsykes
4

Haskell, 41 octets

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

Une solution simple.

xnor
la source
4

Bash + coreutils, 51

eval set {$1}*{$2}
bc<<<"scale=4;$6-$8;$7-$3;$2-$4"
  • La ligne 1 construit une expansion d'accolade qui donne le produit cartésien des deux vecteurs et les place dans les paramètres positionnels.
  • La ligne 2 soustrait les termes appropriés; bceffectue l'évaluation arithmétique avec la précision requise.

L'entrée se présente sous la forme de deux listes séparées par des virgules sur la ligne de commande. Sortie sous forme de lignes séparées par des sauts de ligne:

$ ./crossprod.sh 0.95972,0.25833,0.22140 0.93507,-0.80917,-0.99177
-.07705
1.15884
-1.01812
$
Traumatisme numérique
la source
4

MATL , 17 octets

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

La première entrée est a , la seconde est b .

Essayez-le en ligne!

Explication

!              % 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
Luis Mendo
la source
4

Pyth, 16 octets

-VF*VM.<VLQ_BMS2

Essayez-le en ligne: Démonstration

Explication:

-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
Jakube
la source
3

K5, 44 40 37 32 octets

A écrit celui-ci il y a un bon moment et l'a repoussé récemment .

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

En action:

 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

Modifier 1:

4 octets enregistrés en prenant l'entrée comme une liste de listes au lieu de deux arguments distincts:

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)}

Modifier 2:

Économisé 3 octets en calculant une table de recherche avec décodage de 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}

Modifier 3:

Économisez 5 octets en réorganisant l'application pour permettre d'utiliser une définition tacite au lieu d'un lambda local. Malheureusement, cette solution ne fonctionne plus en oK et nécessite l'interpréteur k5 officiel. Je vais devoir croire sur parole jusqu'à ce que je corrige le bogue dans 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}
JohnE
la source
3

Rubis , 49 octets

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

Essayez-le en ligne!

De retour après 2 ans, j'ai réduit 12 octets en utilisant la façon dont Ruby traite les indices de tableau négatifs. -1est le dernier élément du tableau, -2l'avant-dernier etc.

Rubis, 57

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

En programme de test

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]]
Level River St
la source
2

Python, 73 48 octets

Merci @FryAmTheEggman

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

Ceci est basé sur la définition des composants du produit vectoriel croisé.

Essayez-le ici

TanMath
la source
lambda (a,b,c),(d,e,f):...devrait économiser beaucoup.
FryAmTheEggman
@FryAmTheEggman Vous avez raison. J'ai oublié que lambda peut spécifier comment l'argument doit être.
TanMath
2

Gelée , 5 octets

[[x1,x2],[y1,y2],[z1,z2]]Z

ṁ4ÆḊƝ

Essayez-le en ligne!

Voici une explication PDF au cas où le démarquage SE ne pourrait pas le gérer.


Le produit croisé sous forme analytique

(x1,y1,z1)v1(x2,y2,z2)v2

v1=x1i+y1j+z1k
v2=x2i+y2j+z2k

Oxyz

v1×v2=(x1i+y1j+z1k)×(x2i+y2j+z2k)

i×j=k,i×k=j,j×i=k,j×k=i,k×i=j,k×j=i

Après les réarrangements et calculs nécessaires:

v1×v2=(y1z2z1y2)i+(z1x2x1z2)j+(x1y2y1x2)k

La relation étroite avec les déterminants matriciels

Il y a une chose intéressante à noter ici:

x1y2y1x2=|x1y1 x2y2|
z1x2x1z2=|z1x1 z2x2|
y1z2z1y2=|y1z1 y2z2|

||

Explication du code de gelée

Eh bien ... pas grand chose à expliquer ici. Il génère juste la matrice:

(x1y1z1x1 x2y2z2x2)

Et pour chaque paire de matrices voisines, il calcule le déterminant de la matrice formée en joignant les deux.

ṁ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.
M. Xcoder
la source
1

ES6, 40 octets

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

44 octets si l'entrée doit être composée de deux tableaux:

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

52 octets pour une version plus intéressante:

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

Julia 0,7 , 45 39 octets

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

Essayez-le en ligne!

Utilise la formule basée sur les déterminants donnée dans la description de la tâche.

Merci à H.PWiz pour -6 octets.

Kirill L.
la source
39 octets avec deux astuces:f(a,b)=1:3 .|>i->det([eye(3)[i,:] a b])
H.PWiz
0

APL (NARS), 23 caractères, 46 octets

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

tester:

  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 
RosLuP
la source