16
\$\begingroup\$

The cross product is a peculiarly 3-dimensional phenomenon. There are multiple ways of generalizing it, but each of them have trade offs.

If you require that a cross product be a product of two vectors \$\mathbf{v}_1\times\mathbf{v}_2\$ such that it is:

  • linear, \$a\mathbf{v}_1\times\mathbf{v}_2 = a\left(\mathbf{v}_1\times\mathbf{v}_2\right)\$ and \$\left(\mathbf v_1+\mathbf v_2\right)\times\mathbf v_3 = \left(\mathbf v_1\times\mathbf v_3\right)+\left(\mathbf v_2\times\mathbf v_3\right)\$
  • anticommutative, \$\left(\mathbf{v}_1\times\mathbf{v}_2\right) + \left(\mathbf{v}_2\times\mathbf{v}_1\right) = \mathbf{0}\$
  • orthogonal, \$\left(\mathbf{v}_1\times\mathbf{v}_2\right)\cdot\mathbf v_1 = \mathbf 0\$
  • not everywhere zero

Then there are two dimensions that have cross products:

  • There is the ordinary cross product in 3D.
  • There is also a cross product in 7D.

Today our challenge is to implement this 7-dimensional cross product.

Definition

Although the above is a technically unambiguous challenge specification, I will give a complete definition of a 7D cross product here which you can readily implement as an algorithm.

In order to determine the cross product of two vectors you only need to know the behavior on the basis vectors. You can write each vector as a combination of basis vectors, e.g.

\$ \left[a,b,c,d,e,f,g\right]^\top = a\mathbf e_1 + b\mathbf e_2 + c\mathbf e_3 + d\mathbf e_4 + e\mathbf e_5 + f\mathbf e_6 + g\mathbf e_7 \$

Since the product is linear you can distribute until any cross product is written as the sum of products of basis vectors. For example here's a 3D case:

\begin{align} \left[a,b,c\right]^\top\times\left[x,y,z\right]^\top &= \left(a\mathbf e_1 + b\mathbf e_2 + c\mathbf e_3\right)\times\left(x\mathbf e_1 + y\mathbf e_2 + z\mathbf e_3\right) \\ &= \begin{matrix}& ax\left(e_1\times e_1\right) &+& bx\left(e_2\times e_1\right) &+& cx\left(e_3\times e_1\right) \\+& ay\left(e_1\times e_2\right) &+& by\left(e_2\times e_2\right) &+& cy\left(e_3\times e_2\right) \\+& az\left(e_1\times e_3\right) &+& bz\left(e_2\times e_3\right) &+& cy\left(e_3\times e_3\right)\end{matrix} \end{align}

Then for the product of basis vectors you can use the following product table:

× \$\mathbf e_1\$ \$\mathbf e_2\$ \$\mathbf e_3\$ \$\mathbf e_4\$ \$\mathbf e_5\$ \$\mathbf e_6\$ \$\mathbf e_7\$
\$\mathbf e_1\$ 0 \$\mathbf e_3\$ \$-\mathbf e_2\$ \$\mathbf e_5\$ \$-\mathbf e_4\$ \$-\mathbf e_7\$ \$\mathbf e_6\$
\$\mathbf e_2\$ \$-\mathbf e_3\$ 0 \$\mathbf e_1\$ \$\mathbf e_6\$ \$\mathbf e_7\$ \$-\mathbf e_4\$ \$-\mathbf e_5\$
\$\mathbf e_3\$ \$\mathbf e_2\$ \$-\mathbf e_1\$ 0 \$\mathbf e_7\$ \$-\mathbf e_6\$ \$\mathbf e_5\$ \$-\mathbf e_4\$
\$\mathbf e_4\$ \$-\mathbf e_5\$ \$-\mathbf e_6\$ \$-\mathbf e_7\$ 0 \$\mathbf e_1\$ \$\mathbf e_2\$ \$\mathbf e_3\$
\$\mathbf e_5\$ \$\mathbf e_4\$ \$-\mathbf e_7\$ \$\mathbf e_6\$ \$-\mathbf e_1\$ 0 \$-\mathbf e_3\$ \$\mathbf e_2\$
\$\mathbf e_6\$ \$\mathbf e_7\$ \$\mathbf e_4\$ \$-\mathbf e_5\$ \$-\mathbf e_2\$ \$\mathbf e_3\$ 0 \$-\mathbf e_1\$
\$\mathbf e_7\$ \$-\mathbf e_6\$ \$\mathbf e_5\$ \$\mathbf e_4\$ \$-\mathbf e_3\$ \$-\mathbf e_2\$ \$\mathbf e_1\$ 0

Rules

This is so the goal is to minimize the size of your source code as measured in bytes.

You should take input as two vectors. You may approximate real numbers in any reasonable manner.

You may choose to take input in a way that permutes the basis vectors or multiply the result by -1, so long as it satisfies the definition of the cross product above.

Test cases

The table above provides 49 basic test cases. In addition I suggest you test the two linearity properties with random vectors. If your product is bilinear and satisfies the multiplication table above then it must be correct.

That is:

  • Take two random vectors and two random real numbers and test that \$a\mathbf{v}_1\times b\mathbf{v}_2 = ab\left(\mathbf{v}_1\times\mathbf{v}_2\right)\$
  • Take 3 random vectors and test that \$\left(\mathbf v_1+\mathbf v_2\right)\times\mathbf v_3 = \left(\mathbf v_1\times\mathbf v_3\right)+\left(\mathbf v_2\times\mathbf v_3\right)\$
\$\endgroup\$
5
  • \$\begingroup\$ "Although the above is technically unambiguous, I will give a complete definition of the 7D cross product here which you can readily implement as an algorithm." << This seems to be in contradiction with the wikipedia page, which if I understand it correctly, tells me that there can be many choices of seven-dimensional cross-product? \$\endgroup\$
    – Stef
    Commented 2 days ago
  • \$\begingroup\$ @Stef The constraints are an unambiguous challenge, not a definition of the cross product. The point of this sentence is "ok I've technically given the challenge, but here's a solution you can use". And likewise I'm not trying to say that permutations are exhaustive, just that they are one way to get more products. I've tried tweaking the wording a bit, let me know if there's something else you think could be changed, or feel free to edit the question directly. \$\endgroup\$
    – Wheat Wizard
    Commented yesterday
  • \$\begingroup\$ can output be 15-dimensional vector (codegolf.stackexchange.com/a/282853)? \$\endgroup\$ Commented yesterday
  • \$\begingroup\$ @Lucenaposition Mathematically speaking, the condition for orthogonality requires the output of the cross product operation to have the same dimensionality as the inputs. And it doesn't look like there's anything in the challenge statement that allowed a 15-component output to be interpreted as a 7-dimensional mathematical vector (say, by dropping components or some such thing), but I'm not the authority.... \$\endgroup\$
    – David Z
    Commented 12 hours ago
  • \$\begingroup\$ @Stef In 3-d the properties above don't define the cross product uniquely, there is still a sign ambiguity. In 7-d you only need the cross product to be orthogonal to the 2 input vectors, which still gives you a 5-d space to choose from. But up to that choice, the cross products are all the same. So the multiplication table chooses a particular realization but all realizations are equivalent. \$\endgroup\$
    – quarague
    Commented 1 hour ago

7 Answers 7

12
\$\begingroup\$

JavaScript (ES6), 83 bytes

Expects (u)(v).

u=>v=>[0,1,2,4].reduce((p,i)=>p.map(n=>i&&n+u[i%=7]*v[j%=7]-u[j++]*v[i++],j=i*3),u)

Try it online!

Commented

u =>              // u[] = first vector
v =>              // v[] = second vector
[0, 1, 2, 4]      // lookup list
.reduce((p, i) => // for each value i with p[] as the accumulator:
  p.map(n =>      //   for each value n in p[]:
    i &&          //     force to zero if i = 0
    n +           //     otherwise, take the current value n
    u[i %= 7] *   //     and add u[i] * v[j] - u[j] * v[i]
    v[j %= 7] -   //     where both i and j are reduced modulo 7
    u[j++] *      //     and incremented afterwards
    v[i++],       //
    j = i * 3     //     start with j = i * 3, which gives (modulo 7):
                  //     (i,j) = (1,3), (2,6), (4,5)
  ),              //   end of map()
  u               //   start with p[] = u[] (but the content of p[]
                  //   is cleared on the first iteration)
)                 // end of reduce()
\$\endgroup\$
6
\$\begingroup\$

Wolfram Language (Mathematica), 62 bytes

s&@Do[s[[t]]+=#[[t=Mod[i+{0,1,3},7,1]]]#2[[t]],{i,s=0#;7}]&

-1 bytes thanks to @att.

Try it online!

(\[Cross], unicode U+F4A0) is a special character in Mathematica that represents cross product.

First initialize the result \$\mathbf{s}\$ to a zero vector of length 7. And then:

  • \$(s_1, s_2, s_4) \leftarrow (s_1, s_2, s_4) + (a_1, a_2, a_4) \times (b_1, b_2, b_4)\$ (where \$\times\$ is the 3D cross product);
  • \$(s_2, s_3, s_5) \leftarrow (s_2, s_3, s_5) + (a_2, a_3, a_5) \times (b_2, b_3, b_5)\$;
  • \$\ldots\ldots\$
  • \$(s_7, s_1, s_3) \leftarrow (s_7, s_1, s_3) + (a_7, a_1, a_3) \times (b_7, b_1, b_3)\$.

Now \$\mathbf{s}\$ becomes the 7D cross product of \$\mathbf{a}\$ and \$\mathbf{b}\$.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ -1 byte \$\endgroup\$
    – att
    Commented yesterday
  • \$\begingroup\$ Does Mathematica have a build in Octonian multiplication that one could use (even if it is not shorter)? \$\endgroup\$
    – quarague
    Commented 1 hour ago
  • \$\begingroup\$ @quarague There are some 3rd-party packages for that, but there isn't a built-in. \$\endgroup\$
    – alephalpha
    Commented 32 mins ago
4
\$\begingroup\$

Python3, 216 bytes

def f(v,V):
 t=[[0],[-3,0],[2,-1,0],[-5,-6,-7,0],[4,-7,6,-1,0],[7,4,-5,-2,3,0],[-6,5,4,-3,-2,1,0]]
 D={}
 for x in range(7):
  for y in range(7):D[u]=D.get(u:=t[x][y]if y<len(t[x])else -t[y][x],0)+v[x]*V[y]
 return D

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ This is invalid: it gives a 15-dimensional vector not a 7-dimensional vector. \$\endgroup\$ Commented yesterday
  • \$\begingroup\$ @Lucenaposition D contains only partially reduced terms for the sake of space, full reduction to 7-dimensions can be done by adding 25 more bytes. The full reduction is unnecessary to pass the test cases. \$\endgroup\$
    – Ajax1234
    Commented yesterday
  • \$\begingroup\$ The condition of orthogonality requires the output vector to have the same dimension as the input vector. Your submission fails this (input is 7d, output is 15d) so it might be removed or edited. \$\endgroup\$ Commented 11 hours ago
4
\$\begingroup\$

Charcoal, 63 35 bytes

IE⁷ΣEE⁷⊗﹪⁻μι⁷∧λ×⎇&λ⊖λ§θ⁻ιλ±§θ⁺μλ§ημ

Try it online! Link is to verbose version of code. No test suite because that requires renaming the variables. Explanation: Uses the C(+) octonion multiplication table that I found here (warning: no SSL available).

  ⁷                                 Literal integer `7`
 E                                  Map over implicit range
      ⁷                             Literal integer `7`
     E                              Map over implicit range
          μ                         Inner index
         ⁻                          Subtract
           ι                        Outer value
        ﹪                           Modulo
            ⁷                       Literal integer `7`
       ⊗                            Doubled
    E                               Map over values
              λ                     Inner value
             ∧                      Logical And
                  λ                 Inner value
                 &                  Bitwise And
                    λ               Inner value
                   ⊖                Decremented
                ⎇                   If true then
                      θ             First input
                     §              Cyclically indexed by
                        ι           Outer value
                       ⁻            Subtract
                         λ          Inner value
                            θ       Else first input
                           §        Cyclically indexed by
                              μ     Inner index
                             ⁺      Plus
                               λ    Inner value
                          ±         Negated
               ×                    Multiplied by
                                 η  Second input
                                §   Indexed by
                                  μ Inner index
   Σ                                Take the sum
I                                   Cast to string
                                    Implicitly print
\$\endgroup\$
3
\$\begingroup\$

Maple,  187  176 bytes

(s,t)->eval(s^+.Matrix([[],[-e3],[e2,-e1],[-e5,-e6,-e7],[e4,-e7,e6,-e1],[e7,e4,-e5,-e2,e3],[-e6,e5,e4,-e3,-e2,e1,0]],shape=antisymmetric).t,{seq(e||i=Vector(7,{i=1}),i=1..7)});

If the two vectors are s and t, and Q is the multiplication table as a matrix, then the result in the form a*e1+b*e2+... is sT.Q.t. Then substitute e1, e2 etc with the unit vectors [1,0,0,0,0,0,0]T, [0,1,0,0,0,0,0]T etc. to get the final result.

\$\endgroup\$
3
\$\begingroup\$

PARI/GP, 74 bytes

f(a,b)=[sum(n=0,2,a[u=(i+2^n)%7+1]*b[v=(i+3<<n)%7+1]-b[u]*a[v])|i<-[0..6]]

Attempt This Online!

A port of Arnauld's JavaScript solution.


PARI/GP, 97 bytes

f(a,b)=Vecrev(sum(t=0,6,matdet([x^t,x^u=t++%7,x^v=(t+2)%7;a[t],a[u++],a[v++];b[t],b[u],b[v]])),7)

Attempt This Online!

Using the algorithm in my Mathematica answer.

\$\endgroup\$
2
\$\begingroup\$

Python 2, 165 146 bytes

def g(x,y):
 x*=2;y*=2;z=[0]*10;p,q,r=0,1,3
 for a in range(7)*3:p,q,r=q,r,p;z[a+p]+=x[a+q]*y[a+r]-x[a+r]*y[a+q]
 exec'print sum(z[p::7]);p+=1;'*7

Attempt This Online!

Changed my approach completely.

This is now a port of Seven-dimensional cross product.

Prints output to stdout.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.