クロス積を見つける


20

外積 2つの3次元ベクトルの及びユニークベクターでように:abc

  • c双方に直交する及びab

  • 大きさによって形成される平行四辺形の面積に等しい及びcab

  • 方向、、および、そのためには、続く右手の法則をabc

クロス積にはいくつかの同等の式がありますが、1つは次のとおりです。

a×b=det[ijka1a2a3b1b2b3]

ここで、ij、およびkは、1次元、2次元、および3次元の単位ベクトルです。

チャレンジ

2つの3Dベクトルが与えられたら、完全なプログラムまたは関数を記述して、それらの外積を見つけます。特に外積を計算する組み込み関数は許可されていません。

入力

それぞれ3つの実数の2つの配列。言語に配列がない場合は、数値を3つにグループ化する必要があります。両方のベクトルの大きさは<216です。クロス積は非可換(a×b=(b×a)であるため、順序を指定する方法が必要です。

出力

各コンポーネントが4つの有効数字または104いずれか緩い方まで正確な、適切な形式のクロス積。科学表記法はオプションです。

テストケース

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

これはであるため、バイト単位の最短ソリューションが優先されます。

Maltysenも同様の課題を投稿しましたが、回答は貧弱で、質問は編集されませんでした。


入力を2D配列として取得できますか?
デニス

はい、2が外側の寸法である限り。
リルトシアスト

回答:


14

ゼリー、14 13 12バイト

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

オンラインでお試しください!

使い方

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

非競合バージョン(10バイト)

OK、これは恥ずかしいことですが、配列操作言語Jellyには、これまで配列回転用のビルトインがありませんでした。この新しいビルトインにより、さらに2バイトを節約できます。

ṙ-×
ç_ç@ṙ-

これは、@ AlexA。のJ answerのアプローチを使用していますオンラインでお試しください!

使い方

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

各ペアをベース-1から変換しますか?それはただの悪です。+1
ETHproductions

10

LISP、128 122バイト

こんにちは!これは私のコードです:

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

私はそれが最短の解決策ではないことを知っていますが、今まで誰もLispで提供していませんでした:)

ここに次のコードをコピーして貼り付けて、試してください!

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

プログラミングパズルとCode Golf Stack Exchangeへようこそ。これは素晴らしい答えです、+ 1。勝つことはないだろう言語で答えるのはよくできているが、それでも負荷をかけてゴルフする。多くの場合、コードゴルフの課題は、言語間の問題というよりも言語内の問題です。
wizzwizz4

9

Dyalog APL、12バイト

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

@AlexA。のJ回答に基づいており、(偶然)その回答のコメントセクションの@randomraの改善と同等です。

TryAPLでオンラインで試してください。

使い方

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バイト

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

これは、左右の配列を受け入れ、それらの外積を返す2進動詞です。

説明:

         *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

例:

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

ここで試してみてください

randomraのおかげで13バイト節約されました!


@randomraそれはすごい、ありがとう!私はJの専門家ではないので、それがどのように正確に機能するかをまだ理解していますが、一般的な考えはあります。
アレックスA.

いくつかの説明:*2&|.は、2つの動詞の分岐です:*2&|.。左入力に2右回転入力を乗算します。このフォークはに格納されるvため、を記述v~すると(*2&|.)~、に相当し~ます。この場合、括弧で囲まれた部分の左右の入力パラメーターがスワップされます。
-randomra

@randomraさて、それは理にかなっています。再度、感謝します!
アレックスA.

6

C、156の 154 150 148 144バイト

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

長い間賞品を獲得するつもりはありませんが、とにかくやりたいと思いました。

  • 入力はコンポーネントの改行またはスペース区切りリスト(a1 a2 a3 b1 b2 b3)、出力はスペース区切り(c1 c2 c3)です。
  • 2つの入力ベクトルのインデックスを周期的に並べ替えて積を計算します-行列式を書き出すよりも少ない文字で済みます!

デモ

ゴルフをしていない:

#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
プログラミングパズルとCode Golf Stack Exchangeへようこそ。これは素晴らしい答えです。ゴルフの言語に勝るもののない言語で答えることができました。+1。
wizzwizz4

2
最初のfor必要はありません{}
削除

乾杯、更新。
calvinsykes

1
&v [6-i]をv + 6-iに置き換えることができます。また、j = i%3およびk =(i + 1)%3の後のセミコロンをコンマに置き換えることができます。これにより、forの後の​​すべてが単一ステートメントになるため、{}を省略できます。最後に、2番目のforループでiを1に初期化すると、増分をk = ++ i%3に移動して、括弧をいくつか節約できます。警告が気にならず、適切なバージョンのCを使用している場合は、インクルードもスキップできます。
アルキミスト

素晴らしい、乾杯!私のコンパイラはヘッダーの省略を受け入れないので、ビルドできるバージョンにこだわっています。
-calvinsykes

4

Haskell、41バイト

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

簡単なソリューション。


4

Bash + coreutils、51

eval set {$1}*{$2}
bc<<<"scale=4;$6-$8;$7-$3;$2-$4"
  • 1行目は、2つのベクトルのデカルト積を与えるブレース展開を構築し、それらを位置パラメーターに設定します。
  • 行2は適切な項を引きます。bc必要な精度で算術評価を行います。

入力は、コマンドライン上の2つのコンマ区切りリストとして行われます。改行で区切られた行として出力:

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

4

MATL、17バイト

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

最初の入力はa、2番目はbです。

オンラインでお試しください!

説明

!              % 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バイト

-VF*VM.<VLQ_BMS2

オンラインで試す:デモンストレーション

説明:

-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バイト

かなり前にこれを書いて 最近再びそれ振り払った

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

動作中:

 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

編集1:

入力を2つの個別の引数ではなくリストのリストとして取得することにより、4バイトを節約しました。

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

編集2:

base-decodeでルックアップテーブルを計算することで3バイトを節約しました。

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}

編集3:

ローカルラムダの代わりに暗黙の定義を使用できるようにアプリケーションを再配置して、5バイトを節約します。残念ながら、このソリューションはoKでは動作しなくなり、公式のk5インタープリターが必要です。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

ルビー、49バイト

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

オンラインでお試しください!

2年後に戻って、Rubyが負の配列インデックスを処理する方法を使用して、12バイトを削減しました。 -1配列の最後の要素、最後-2から2番目の要素などです。

ルビー、57

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

テストプログラムで

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バイト

ありがとう@FryAmTheEggman

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

これは、ベクトル外積のコンポーネント定義に基づいています。

ここで試してみてください


lambda (a,b,c),(d,e,f):...かなり節約できるはずです。
FryAmTheEggman

@FryAmTheEggmanそうですね。lambdaが引数の方法を指定できることを忘れていました。
-TanMath

2

ゼリー、5バイト

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

ṁ4ÆḊƝ

オンラインでお試しください!

SEマークダウンで処理できない場合のPDFの説明を次に示します。


分析形式のクロスプロダクト

(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

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.



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

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.


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 

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.