Trova il prodotto incrociato


20

Il prodotto incrociato di due vettori tridimensionali e è il vettore unico tale che:un'Bc

  • c è ortogonale a eun'B

  • L'ampiezza di è uguale all'area del parallelogramma formata da ecab

  • Le direzioni di , e , in questo ordine, seguono la regola della mano destra .abc

Esistono alcune formule equivalenti per prodotti incrociati, ma una è la seguente:

a×b=det[ijka1a2a3b1b2b3]

dove i , j e k sono i vettori di unità nella prima, seconda e terza dimensione.

Sfida

Dati due vettori 3D, scrivere un programma completo o una funzione per trovare il loro prodotto incrociato. Non sono consentiti builtin che calcolano specificamente il prodotto incrociato.

Ingresso

Due matrici di tre numeri reali ciascuna. Se la tua lingua non ha matrici, i numeri devono comunque essere raggruppati in tre. Entrambi i vettori avranno magnitudo <216 . Nota che il prodotto incrociato non è comunicativo ( a×b=(b×a) ), quindi dovresti avere un modo per specificare l'ordine.

Produzione

Il loro prodotto incrociato, in un formato ragionevole, con ogni componente preciso a quattro cifre significative o 104 , a seconda di quale sia più sciolto. La notazione scientifica è facoltativa.

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

Questo è , quindi vince la soluzione più breve in byte.

Maltysen ha pubblicato una sfida simile , ma la risposta è stata scarsa e la domanda non è stata modificata.


L'input può essere preso come un array 2D?
Dennis,

Sì, purché 2 sia la dimensione esterna.
lirtosiast

Risposte:


14

Gelatina, 14 13 12 byte

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

Provalo online!

Come funziona

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

Versione non competitiva (10 byte)

OK, questo è imbarazzante, ma il linguaggio di manipolazione dell'array Jelly non aveva un built-in per la rotazione dell'array fino ad ora. Con questo nuovo built-in, possiamo salvare due byte aggiuntivi.

ṙ-×
ç_ç@ṙ-

Questo utilizza l'approccio della risposta J di @ AlexA . Provalo online!

Come funziona

ṙ-×     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).

Convertire ogni coppia dalla base -1? Questo è solo male. +1
ETHproductions

10

LISP, 128 122 byte

Ciao! Questo è il mio codice:

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

So che non è la soluzione più breve, ma nessuno ne ha fornito uno a Lisp, fino ad ora :)

Copia e incolla il seguente codice qui per provarlo!

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

Benvenuti in Puzzle di programmazione e scambio di code golf stack. Questa è un'ottima risposta, +1. Ben fatto per aver risposto in una lingua che non vincerà, ma continuerà a giocare a golf. Spesso le sfide del code-golf riguardano più le lingue che tra loro!
wizzwizz4,

9

Dyalog APL, 12 byte

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

Basato sulla risposta J di @ AlexA. e (per coincidenza) equivalente al miglioramento di @ randomra nella sezione commenti di quella risposta.

Provalo online su TryAPL .

Come funziona

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 byte

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

Questo è un verbo diadico che accetta array a sinistra e a destra e restituisce il loro prodotto incrociato.

Spiegazione:

         *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

Esempio:

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

Provalo qui

Salvato 13 byte grazie a randomra!


@randomra È fantastico, grazie! Non sono un esperto di J, quindi sto ancora cercando di capire come funziona esattamente ma ho un'idea generale.
Alex A.

Alcuni chiarimenti: *2&|.è un fork di due verbi: *e 2&|.. Moltiplica l'ingresso sinistro per un ingresso ruotato di 2 destro. Questo fork è memorizzato in vmodo che quando scriviamo v~, è equivalente a (*2&|.)~, dove ~scambia i parametri di input sinistro e destro per la parte tra parentesi.
randomra,

@randomra Va bene, ha senso. Grazie ancora!
Alex A.

6

C, 156 154 150 148 144 byte

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

Non vincerò alcun premio per la durata, ma ho pensato di provare comunque.

  • L'input è un elenco di componenti delimitato da nuova riga o spazio (ovvero a1 a2 a3 b1 b2 b3), l'output è delimitato da spazi (ovvero c1 c2 c3).
  • Permette ciclicamente gli indici dei due vettori di input per calcolare il prodotto - richiede meno caratteri rispetto alla scrittura dei determinanti!

dimostrazione

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

1
Benvenuti in Puzzle di programmazione e scambio di code golf stack. Questa è un'ottima risposta; ben fatto per rispondere in una lingua che non batterà le lingue del golf. +1.
wizzwizz4,

2
Il tuo primo fornon ha bisogno{}
rimosso il

evviva, aggiornato.
Calvinsykes,

1
Puoi sostituire & v [6-i] con v + 6-i. Inoltre, puoi sostituire il punto e virgola dopo j = i% 3 e k = (i + 1)% 3 con virgole, il che rende tutto dopo il per una singola istruzione in modo da poter omettere {}. Infine, se inizializzi da i a 1 per il secondo ciclo, puoi spostare l'incremento in k = ++ i% 3 salvando un paio di parentesi. Se non sei preoccupato per gli avvisi e usi la versione corretta di C, puoi anche saltare l'inclusione.
Alchymist,

fantastico, evviva! Il mio compilatore non accetta l'omissione dell'intestazione, quindi mi sono bloccato con una versione che sono in grado di creare.
Calvinsykes,

4

Haskell, 41 byte

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

Una soluzione semplice.


4

Bash + coreutils, 51

eval set {$1}*{$2}
bc<<<"scale=4;$6-$8;$7-$3;$2-$4"
  • La linea 1 costruisce un'espansione del controvento che fornisce il prodotto cartesiano dei due vettori e li imposta nei parametri posizionali.
  • La riga 2 sottrae i termini appropriati; bcesegue la valutazione aritmetica con la precisione richiesta.

L'input è come due elenchi separati da virgola sulla riga di comando. Output come linee separate da nuova riga:

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

4

MATL , 17 byte

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

Il primo input è a , il secondo è b .

Provalo online!

Spiegazione

!              % 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 byte

-VF*VM.<VLQ_BMS2

Provalo online: dimostrazione

Spiegazione:

-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 byte

L' ho scritto un po 'di tempo fa e l' ho rispolverato di recente .

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

In azione:

 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

Modifica 1:

Ho salvato 4 byte prendendo l'input come un elenco di elenchi anziché due argomenti separati:

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

Modifica 2:

Salvato 3 byte calcolando una tabella di ricerca con decodifica 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}

Modifica 3:

Salvare 5 byte riorganizzando l'applicazione per consentire l'utilizzo di una definizione tacita anziché di una lambda locale. Sfortunatamente, questa soluzione non funziona più in oK e richiede l'interprete k5 ufficiale. Devo prendere la mia parola per questo finché non risolverò il bug in 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

Rubino , 49 byte

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

Provalo online!

Di ritorno dopo 2 anni, mi sono rasato 12 byte usando come Ruby tratta gli indici di array negativi. -1è l'ultimo elemento dell'array, -2il secondo ultimo ecc.

Ruby, 57

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

Nel programma di 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]]

2

Python, 73 48 byte

Grazie @FryAmTheEggman

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

Questo si basa sulla definizione del componente del prodotto incrociato vettoriale.

Provalo qui


lambda (a,b,c),(d,e,f):...dovrebbe risparmiare molto.
FryAmTheEggman,

@FryAmTheEggman Hai ragione. Ho dimenticato che lambda può specificare come dovrebbe essere l'argomento.
TanMath,

2

Gelatina , 5 byte

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

ṁ4ÆḊƝ

Provalo online!

Ecco una spiegazione in PDF nel caso in cui il markdown SE non sia in grado di gestirlo.


Il prodotto incrociato in forma analitica

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

v1=X1io+y1j+z1K
v2=X2io+y2j+z2K

OXyz

v1×v2=(X1io+y1j+z1K)×(X2io+y2j+z2K)

io×j=K,io×K=-j,j×io=-K,j×K=io,K×io=j,K×j=-io

Dopo i riarrangiamenti e i calcoli necessari:

v1×v2=(y1z2-z1y2)io+(z1X2-X1z2)j+(X1y2-y1X2)K

La stretta relazione con i determinanti della matrice

C'è una cosa interessante da notare qui:

X1y2-y1X2=|X1y1 X2y2|
z1X2-X1z2=|z1X1 z2X2|
y1z2-z1y2=|y1z1 y2z2|

||

Spiegazione del codice Jelly

Bene ... non c'è molto da spiegare qui. Genera solo la matrice:

(X1y1z1X1 X2y2z2X2)

E per ogni coppia di matrici vicine, calcola il determinante della matrice formata unendo le due.

ṁ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 byte

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

44 byte se l'input deve essere di due array:

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

52 byte per una versione più interessante:

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

1

Julia 0.7 , 45 39 byte

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

Provalo online!

Utilizza la formula basata su determinante fornita nella descrizione dell'attività.

Grazie a H.PWiz per -6 byte.


39 byte con due trucchi:f(a,b)=1:3 .|>i->det([eye(3)[i,:] a b])
H.Piz,

0

APL (NARS), 23 caratteri, 46 byte

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.