Temukan Produk Silang

20

Produk silang dari dua vektor tiga dimensi a dan b adalah vektor unik c sedemikian rupa sehingga:

  • c adalah ortogonal untuka danb

  • Besarnya c sama dengan luas jajaran genjang yang dibentuk oleh a dan b

  • Arah a , b , dan c , dalam urutan itu, ikuti aturan sebelah kanan .

Ada beberapa rumus setara untuk produk silang, tetapi satu adalah sebagai berikut:

a×b=det[ijka1a2a3b1b2b3]

di mana i , j , dan k adalah vektor satuan dalam dimensi pertama, kedua, dan ketiga.

Tantangan

Diberi dua vektor 3D, tulis satu program penuh atau fungsi untuk menemukan produk silang mereka. Builtin yang secara spesifik menghitung produk silang tidak diizinkan.

Memasukkan

Dua array masing-masing tiga bilangan real. Jika bahasa Anda tidak memiliki array, angka-angka masih harus dikelompokkan menjadi tiga. Kedua vektor akan memiliki magnitudo <216 . Perhatikan bahwa produk silang adalah nonkomunikasi ( a×b=(b×a) ), jadi Anda harus memiliki cara untuk menentukan pesanan.

Keluaran

Produk silang mereka, dalam format yang masuk akal, dengan setiap komponen akurat hingga empat angka signifikan atau 104 , mana yang lebih longgar. Notasi ilmiah bersifat opsional.

Uji kasus

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

Ini adalah , jadi solusi terpendek dalam byte menang.

Maltysen memposting tantangan serupa , tetapi tanggapannya buruk dan pertanyaannya tidak diedit.

lirtosiast
sumber
Bisakah input diambil sebagai array 2D?
Dennis
Ya, selama 2 adalah dimensi luar.
lirtosiast

Jawaban:

14

Jelly, 14 13 12 byte

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

Cobalah online!

Bagaimana itu bekerja

;"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 tidak bersaing (10 byte)

OK, ini memalukan, tetapi bahasa manipulasi array Jelly tidak memiliki built-in untuk rotasi array sampai sekarang. Dengan built-in yang baru ini, kita dapat menyimpan dua byte tambahan.

ṙ-×
ç_ç@ṙ-

Ini menggunakan pendekatan dari jawaban J @ AlexA . Cobalah online!

Bagaimana itu bekerja

ṙ-×     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
sumber
Konversi setiap pasangan dari basis -1? Itu jahat. +1
ETHproduksi
10

PELAT, 128 122 byte

Hai! Ini kode saya:

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

Saya tahu bahwa itu bukan solusi terpendek, tetapi tidak ada yang memberikan satu di Lisp, sampai sekarang :)

Salin dan tempel kode berikut di sini untuk mencobanya!

(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
sumber
Selamat datang di Programming Puzzles dan Code Golf Stack Exchange. Ini adalah jawaban yang bagus, +1. Dilakukan dengan baik untuk menjawab dalam bahasa yang tidak akan menang, tetapi masih bisa memuatnya. Seringkali tantangan kode-golf lebih banyak tentang dalam bahasa daripada di antara mereka!
wizzwizz4
9

Dyalog APL, 12 byte

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

Berdasarkan jawaban J @ AlexA. Dan (kebetulan) setara dengan peningkatan @ randomra di bagian komentar jawaban itu.

Cobalah online di TryAPL .

Bagaimana itu bekerja

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

J, 27 14 byte

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

Ini adalah kata kerja diad yang menerima array di kiri dan kanan dan mengembalikan produk silang mereka.

Penjelasan:

         *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

Contoh:

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

Coba di sini

Disimpan 13 byte berkat randomra!

Alex A.
sumber
@randomra Itu luar biasa, terima kasih! Saya bukan ahli J jadi saya masih mencari tahu bagaimana tepatnya kerjanya tapi saya punya ide umum.
Alex A.
Beberapa klarifikasi: *2&|.adalah fork dari dua kata kerja: *dan 2&|.. Ini mengalikan input kiri dengan diputar oleh 2 input kanan. Garpu ini disimpan vjadi ketika kita menulis v~, itu setara dengan (*2&|.)~, di mana ~menukar parameter input kiri dan kanan untuk bagian yang di-kurung.
randomra
@randomra Oke, itu masuk akal. Terima kasih lagi!
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]);}

Tidak akan memenangkan hadiah lama, tapi kupikir aku harus tetap pergi.

  • Input adalah daftar komponen yang dibatasi oleh spasi atau spasi baru (yaitu a1 a2 a3 b1 b2 b3), output dibatasi oleh ruang (yaitu c1 c2 c3).
  • Secara siklis memungkinkan indeks dari dua vektor input untuk menghitung produk - mengambil lebih sedikit karakter daripada menuliskan determinan!

Demo

Tidak Terkumpul:

#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
sumber
1
Selamat datang di Programming Puzzles dan Code Golf Stack Exchange. Ini jawaban yang bagus; dilakukan dengan baik untuk menjawab dalam bahasa yang tidak akan mengalahkan bahasa golf. +1.
wizzwizz4
2
Pertama forAnda tidak perlu{}
dihapus
sorakan, diperbarui.
calvinsykes
1
Anda dapat mengganti & v [6-i] dengan v + 6-i. Selain itu, Anda dapat mengganti titik koma setelah j = i% 3 dan k = (i + 1)% 3 dengan koma, yang membuat semuanya setelah untuk satu pernyataan sehingga Anda dapat menghilangkan {}. Akhirnya, jika Anda menginisialisasi i ke 1 untuk loop kedua, Anda dapat memindahkan kenaikan ke k = ++ i% 3 menyimpan beberapa tanda kurung. Jika Anda tidak khawatir tentang peringatan dan menggunakan versi C yang tepat, Anda juga dapat mengabaikannya.
Alchymist
mengagumkan, tepuk tangan! Kompiler saya tidak akan menerima penghapusan header, jadi saya terjebak dengan versi yang saya bisa buat.
calvinsykes
4

Haskell, 41 byte

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

Solusi mudah.

Tidak
sumber
4

Bash + coreutils, 51

eval set {$1}*{$2}
bc<<<"scale=4;$6-$8;$7-$3;$2-$4"
  • Baris 1 membangun ekspansi penjepit yang memberikan produk kartesian dari dua vektor dan menetapkannya ke dalam parameter posisi.
  • Baris 2 mengurangi persyaratan yang sesuai; bcmelakukan evaluasi aritmatika dengan presisi yang diperlukan.

Input adalah sebagai dua daftar yang dipisahkan koma pada baris perintah. Output sebagai baris yang dipisahkan baris baru:

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

MATL , 17 byte

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

Input pertama adalah a , kedua adalah b .

Cobalah online!

Penjelasan

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

Pyth, 16 byte

-VF*VM.<VLQ_BMS2

Cobalah online: Demonstrasi

Penjelasan:

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

K5, 44 40 37 32 byte

Menulis yang ini beberapa waktu yang lalu dan membersihkannya lagi baru-baru ini .

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

Dalam aksi:

 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

Edit 1:

Disimpan 4 byte dengan mengambil input sebagai daftar daftar alih-alih dua argumen terpisah:

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

Edit 2:

Disimpan 3 byte dengan menghitung tabel pencarian dengan basis-decode:

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:

Simpan 5 byte dengan mengatur ulang aplikasi untuk mengizinkan menggunakan definisi diam-diam alih-alih lambda lokal. Sayangnya, solusi ini tidak lagi berfungsi di oK, dan membutuhkan juru bahasa resmi k5. Harus mengambil kata-kata saya untuk yang satu ini sampai saya memperbaiki bug di 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
sumber
3

Ruby , 49 byte

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

Cobalah online!

Kembali setelah 2 tahun, saya mencukur 12 byte dengan menggunakan cara Ruby memperlakukan indeks array negatif. -1adalah elemen terakhir dari array, -2yang terakhir terakhir dll.

Ruby, 57

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

Dalam program uji

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

Python, 73 48 byte

Terima kasih @FryAmTheEggman

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

Ini didasarkan pada definisi komponen produk lintas vektor.

Coba di sini

TanMath
sumber
lambda (a,b,c),(d,e,f):...harus menghemat banyak.
FryAmTheEggman
@FryAmTheEggman Anda benar. Saya lupa bahwa lambda dapat menentukan bagaimana seharusnya argumen itu.
TanMath
2

Jeli , 5 byte

Mengambil input dalam formulir [[x1,x2],[y1,y2],[z1,z2]]. Jika Anda ingin mereka menjadi dua daftar koordinat xyz, cukup tambahkan Zawal program.

ṁ4ÆḊƝ

Cobalah online!

Berikut adalah penjelasan PDF jika penurunan harga SE tidak dapat mengatasinya.


Produk silang dalam bentuk analitik

Membiarkan (x1,y1,z1) menjadi koordinat dari v1 dan (x2,y2,z2) menjadi koordinat dari v2. Ekspresi analitik mereka adalah sebagai berikut:

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
sumber
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
sumber
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.
sumber
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
sumber
0

Pari/GP, 41 bytes

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

Try it online!

alephalpha
sumber