Finden Sie das Kreuzprodukt

20

Das Kreuzprodukt zweier dreidimensionaler Vektoren a und b ist der eindeutige Vektor c so dass:

  • c ist orthogonal zua undb

  • Die Größe von c ist gleich der Fläche des durch a und b gebildeten Parallelogrammsb

  • Die Richtungen von a , b und c folgen in dieser Reihenfolge der Rechtsregel .

Es gibt einige äquivalente Formeln für Kreuzprodukte, aber eine lautet wie folgt:

a×b=det[ijka1a2a3b1b2b3]

Dabei sind i , j und k die Einheitsvektoren in der ersten, zweiten und dritten Dimension.

Herausforderung

Schreiben Sie mit zwei 3D-Vektoren ein vollständiges Programm oder eine Funktion, um das Kreuzprodukt zu finden. Builtins, die spezifisch das Kreuzprodukt berechnen, sind nicht zulässig.

Eingang

Zwei Arrays mit jeweils drei reellen Zahlen. Wenn Ihre Sprache keine Arrays enthält, müssen die Zahlen immer noch in drei Gruppen eingeteilt werden. Beide Vektoren haben eine Größe <216 . Beachten Sie, dass das Kreuzprodukt nicht kommutativ ist ( a×b=(b×a) ), sodass Sie eine Möglichkeit haben sollten, die Reihenfolge anzugeben.

Ausgabe

Ihr Kreuzprodukt in einem vernünftigen Format, wobei jede Komponente auf vier signifikante Zahlen oder 104 genau ist , je nachdem, welcher Wert niedriger ist. Die wissenschaftliche Notation ist optional.

Testfälle

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

Das ist , also gewinnt die kürzeste Lösung in Bytes.

Maltysen postete eine ähnliche Herausforderung , aber die Antwort war schlecht und die Frage wurde nicht bearbeitet.

Lirtosiast
quelle
Kann die Eingabe als 2D-Array verwendet werden?
Dennis
Ja, solange 2 die äußere Abmessung ist.
Lirtosiast

Antworten:

14

Jelly, 14 13 12 Bytes

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

Probieren Sie es online!

Wie es funktioniert

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

Nicht konkurrierende Version (10 Bytes)

OK, das ist peinlich, aber in der Array-Manipulationssprache Jelly war bis jetzt noch keine Funktion für die Array-Rotation integriert. Mit dieser neuen Funktion können zwei zusätzliche Bytes eingespart werden.

ṙ-×
ç_ç@ṙ-

Dies verwendet den Ansatz aus der Antwort von @ AlexA . Probieren Sie es online!

Wie es funktioniert

ṙ-×     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
quelle
Konvertiere jedes Paar von der Basis -1? Das ist nur böse. +1
ETHproductions
10

LISP, 128 122 Bytes

Hallo! Das ist mein 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)))

Ich weiß, dass es nicht die kürzeste Lösung ist, aber bisher hat noch niemand in Lisp eine bereitgestellt :)

Kopieren Sie den folgenden Code und fügen Sie ihn hier ein , um es zu versuchen!

(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
quelle
Willkommen beim Programmieren von Rätseln und beim Code Golf Stack Exchange. Dies ist eine großartige Antwort, +1. Gut gemacht für die Beantwortung in einer Sprache, die nicht gewinnen wird, aber trotzdem jede Menge Golf spielt. Oft geht es bei Code-Golf- Herausforderungen mehr um Sprachen als darum, was sie miteinander zu tun haben!
Wizzwizz4
9

Dyalog APL, 12 Bytes

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

Basierend auf der Antwort von @ AlexA. Und (zufällig) der Verbesserung von @ randomra im Kommentarbereich dieser Antwort.

Probieren Sie es online auf TryAPL aus .

Wie es funktioniert

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
quelle
9

J, 27-14 Bytes

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

Dies ist ein dyadisches Verb, das Arrays links und rechts akzeptiert und deren Kreuzprodukt zurückgibt.

Erläuterung:

         *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

Beispiel:

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

Probieren Sie es hier aus

13 Bytes dank randomra eingespart!

Alex A.
quelle
@randomra Das ist großartig, danke! Da ich kein J-Experte bin, überlege ich mir immer noch, wie es genau funktioniert, aber ich habe eine allgemeine Idee.
Alex A.
Einige Erklärungen: *2&|.besteht aus zwei Verben: *und 2&|.. Es multipliziert die linke Eingabe mit einer um 2 gedrehten rechten Eingabe. Diese Verzweigung ist in gespeichert, vso dass sie beim Schreiben v~gleichbedeutend (*2&|.)~ist mit dem ~Vertauschen der linken und rechten Eingabeparameter für den in Klammern gesetzten Teil.
Randomra
@randomra Okay, das macht Sinn. Danke noch einmal!
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]);}

Ich werde keine Preise für die Länge gewinnen, dachte aber, ich würde es trotzdem versuchen.

  • Die Eingabe ist eine durch Zeilenumbrüche oder Leerzeichen getrennte Liste von Komponenten (dh a1 a2 a3 b1 b2 b3), die Ausgabe ist durch Leerzeichen getrennt (dh c1 c2 c3).
  • Durchläuft zyklisch die Indizes der beiden Eingabevektoren, um das Produkt zu berechnen - benötigt weniger Zeichen als das Ausschreiben der Determinanten!

Demo

Ungolfed:

#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
quelle
1
Willkommen beim Programmieren von Rätseln und beim Code Golf Stack Exchange. Dies ist eine großartige Antwort. Gut gemacht für die Beantwortung in einer Sprache, die die Golfsprachen nicht übertrifft. +1.
wizzwizz4
2
Dein erstes formuss nicht{}
entfernt am
Prost, aktualisiert.
Calvinsykes
1
Sie können & v [6-i] durch v + 6-i ersetzen. Sie können auch das Semikolon nach j = i% 3 und k = (i + 1)% 3 durch Kommas ersetzen, wodurch nach dem alles für eine einzelne Anweisung steht, sodass Sie das {} weglassen können. Wenn Sie schließlich i für die zweite for-Schleife auf 1 initialisieren, können Sie das Inkrement in k = ++ i% 3 verschieben und dabei einige Klammern einsparen. Wenn Sie sich nicht um Warnungen sorgen und die richtige Version von C verwenden, können Sie auch das Include überspringen.
Alchymist
Super, Prost! Mein Compiler akzeptiert das Auslassen des Headers nicht, daher habe ich mich an eine Version gehalten, die ich erstellen kann.
Calvinsykes
4

Haskell, 41 Bytes

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

Eine einfache Lösung.

xnor
quelle
4

Bash + Coreutils, 51

eval set {$1}*{$2}
bc<<<"scale=4;$6-$8;$7-$3;$2-$4"
  • Zeile 1 konstruiert eine Klammererweiterung, die das kartesische Produkt der beiden Vektoren ergibt und diese in die Positionsparameter setzt.
  • Zeile 2 subtrahiert die entsprechenden Terme. bcführt die arithmetische Auswertung mit der erforderlichen Genauigkeit durch.

Die Eingabe erfolgt als zwei durch Kommas getrennte Listen in der Befehlszeile. Ausgabe als Zeilenumbruch:

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

MATL , 17 Bytes

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

Der erste Eingang ist a , der zweite ist b .

Probieren Sie es online!

Erläuterung

!              % 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
quelle
4

Pyth, 16 Bytes

-VF*VM.<VLQ_BMS2

Probieren Sie es online aus: Demonstration

Erläuterung:

-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
quelle
3

K5, 44 40 37 32 Bytes

Schrieb dieses vor einiger Zeit und wischte es vor kurzem wieder ab .

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

In Aktion:

 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

Bearbeiten 1:

4 Bytes durch Eingabe als Liste von Listen anstelle von zwei separaten Argumenten gespeichert:

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

Bearbeiten 2:

3 Bytes durch Berechnung einer Nachschlagetabelle mit Basisdecodierung eingespart:

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}

Edit 3:

Sparen Sie 5 Byte, indem Sie die Anwendung neu anordnen, um die Verwendung einer impliziten Definition anstelle eines lokalen Lambda zuzulassen. Leider funktioniert diese Lösung in OK nicht mehr und erfordert den offiziellen k5-Interpreter. Ich muss mein Wort für dieses nehmen, bis ich den Fehler in OK behebe:

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
quelle
3

Ruby, 49 bytes

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

Try it online!

Returning after 2 years, I shaved off 12 bytes by using how Ruby treats negative array indices. -1 is the last element of the array, -2 the second last etc.

Ruby, 57

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

In test program

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
quelle
2

Python, 73 48 bytes

Thanks @FryAmTheEggman

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

This is based on the component definition of the vector cross product.

Try it here

TanMath
quelle
lambda (a,b,c),(d,e,f):... should save a lot.
FryAmTheEggman
@FryAmTheEggman You are right. I forgot that lambda can specify how the argument should be.
TanMath
2

Jelly, 5 bytes

Takes input in the form [[x1,x2],[y1,y2],[z1,z2]]. If you want them to be two lists of x-y-z coordinates, just prepend Z to the beginning of the program.

ṁ4ÆḊƝ

Try it online!

Here is a PDF explanation in case SE markdown can't handle it.


The cross-product in analytic form

Let (x1,y1,z1) be the coordinates of v1 and (x2,y2,z2) be the coordinates of v2. Their analytic expressions are as follows:

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

The only thing left to do now is to also write their cross-product in terms of its coordinates in the Oxyz space.

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

Keeping in mind that:

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

After the necessary rearrangements and calculations:

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

The close relationship with matrix determinants

There's an interesting thing to note here:

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

Where we use the notation || for matrix determinant. Notice the beautiful rotational symmetry?

Jelly code explanation

Well... not much to explain here. It just generates the matrix:

(x1y1z1x1 x2y2z2x2)

And for each pair of neighbouring matrices, it computes the determinant of the matrix formed by joining the two.

ṁ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.
Mr. Xcoder
quelle
1

ES6, 40 bytes

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

44 bytes if the input needs to be two arrays:

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

52 bytes for a more interesting version:

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

Julia 0.7, 45 39 bytes

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

Try it online!

Uses the determinant-based formula given in the task description.

Thanks to H.PWiz for -6 bytes.

Kirill L.
quelle
39 bytes with two tricks: f(a,b)=1:3 .|>i->det([eye(3)[i,:] a b])
H.PWiz
0

APL(NARS), 23 chars, 46 bytes

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

test:

  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
quelle
0

Pari/GP, 41 bytes

(a,b)->Vec(matdet(Mat([[x^2,x,1],a,b]~)))

Try it online!

alephalpha
quelle