找到叉积


20

两个三维向量ab叉积是唯一向量c,使得:一种bC

  • C正交于一种b

  • 的大小C等于平行四边形的通过形成在区域一种b

  • 的方向一种b,和C,按照这个顺序,遵循右手定则

叉积有一些等效公式,但是一个公式如下:

a×b=det[ijka1a2a3b1b2b3]

其中ijk是第一维,第二维和第三维的单位矢量。

挑战

给定两个3D向量,编写一个完整的程序或函数以查找其叉积。不允许专门计算叉积的内建函数。

输入值

由三个实数组成的两个数组。如果您的语言没有数组,则数字仍必须分为三部分。两个向量的大小将为<216。请注意,叉积是a×b=(b×a)交换的(\ vec a \ times \ vec b =-\ bigl(\ vec b \ times \ vec a \ bigr)),因此您应该有一种指定顺序的方法。

输出量

他们的交叉乘积以合理的格式,每个成分精确到四个有效数字或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。
lirtosiast '16

Answers:


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字节)

好的,这很尴尬,但是数组操纵语言Jelly直到现在还没有内置的数组旋转功能。有了这个新的内置函数,我们可以节省两个额外的字节。

ṙ-×
ç_ç@ṙ-

这使用@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 2016年

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 2016年

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&|.     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专家,所以我仍在弄清楚它的工作原理,但是我有一个总体思路。
Alex A.

一些澄清:*2&|.是两个动词的叉:*2&|.。它将左输入乘以右旋转2的输入。此派生存储在中,v因此当我们编写时v~,它等效于(*2&|.)~,其中~将括号内的部分的左和右输入参数交换。
randomra

@randomra好的,这很有道理。再次感谢!
Alex 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)。
  • 循环排列两个输入向量的索引以计算乘积-比写出行列式占用更少的字符!

演示版

取消高尔夫:

#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 2016年

2
您的第一次for不需要{}

欢呼声,更新。
calvinsykes '16

1
您可以用v + 6-i替换&v [6-i]。另外,您可以用逗号替换j = i%3和k =(i + 1)%3之后的分号,从而在单个语句后加上所有内容,因此可以省略{}。最后,如果将第二个for循环中的i初始化为1,则可以将增量移动到k = ++ i%3并节省几个括号。如果您不担心警告并使用正确的C版本,则也可以跳过包含。
Alchymist '02

太棒了,加油!我的编译器不会接受标头的省略,因此我坚持使用我可以构建的版本。
calvinsykes '16

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行减去相应的项;bc对所需的精度进行算术评估。

输入是命令行上两个逗号分隔的列表。输出为以换行符分隔的行:

$ ./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,第二个输入是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:

通过将输入作为列表列表而不是两个单独的参数来节省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:

通过使用基码计算查找表节省了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个字节,以允许使用默认定义而不是本地lambda。不幸的是,该解决方案不再能正常运行,并且需要官方的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第二个,依此类推。

Ruby,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 '16

@FryAmTheEggman你是对的。我忘记了lambda可以指定参数的方式。
TanMath

2

果冻,5个字节

[[X1个X2][ÿ1个ÿ2][ž1个ž2]]Z

ṁ4ÆḊƝ

在线尝试!

如果SE markdown无法解决问题,这是PDF的说明


分析形式的叉积

X1个ÿ1个ž1个v1个X2ÿ2ž2v2

v1个=X1个一世+ÿ1个Ĵ+ž1个ķ
v2=X2一世+ÿ2Ĵ+ž2ķ

ØXÿž

v1个×v2=X1个一世+ÿ1个Ĵ+ž1个ķ×X2一世+ÿ2Ĵ+ž2ķ

一世×Ĵ=ķ一世×ķ=-ĴĴ×一世=-ķĴ×ķ=一世ķ×一世=Ĵķ×Ĵ=-一世

经过必要的重新安排和计算后:

v1个×v2=ÿ1个ž2-ž1个ÿ2一世+ž1个X2-X1个ž2Ĵ+X1个ÿ2-ÿ1个X2ķ

与矩阵行列式的密切关系

这里有个有趣的事情要注意:

X1个ÿ2-ÿ1个X2=|X1个ÿ1个 X2ÿ2|
ž1个X2-X1个ž2=|ž1个X1个 ž2X2|
ÿ1个ž2-ž1个ÿ2=|ÿ1个ž1个 ÿ2ž2|

||

果冻代码说明

好吧...这里不多解释。它只是生成矩阵:

X1个ÿ1个ž1个X1个 X2ÿ2ž2X2

并且对于每对相邻矩阵,它计算通过将两者结合而形成的矩阵的行列式。

ṁ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个字节

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

如果输入需要为两个数组,则为44个字节:

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

52字节是更有趣的版本:

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

1

朱莉娅0.745个 39字节

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

在线尝试!

使用任务描述中给出的基于行列式的公式。

感谢-6字节的H.PWiz。


39个字节的两个技巧:f(a,b)=1:3 .|>i->det([eye(3)[i,:] a b])
H.PWiz

0

APL(NARS),23个字符,46个字节

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

测试:

  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 

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.