33
\$\begingroup\$

The three-dimensional Levi-Civita symbol is a function f taking triples of numbers (i,j,k) each in {1,2,3}, to {-1,0,1}, defined as:

  • f(i,j,k) = 0 when i,j,k are not distinct, i.e. i=j or j=k or k=i
  • f(i,j,k) = 1 when (i,j,k) is a cyclic shift of (1,2,3), that is one of (1,2,3), (2,3,1), (3,1,2).
  • f(i,j,k) = -1 when (i,j,k) is a cyclic shift of (3,2,1), that is one of (3,2,1), (2,1,3), (1,3,2).

The result is the sign of a permutation of (1,2,3), with non-permutations giving 0. Alternatively, if we associate the values 1,2,3 with orthogonal unit basis vectors e_1, e_2, e_3, then f(i,j,k) is the determinant of the 3x3 matrix with columns e_i, e_j, e_k.

Input

Three numbers each from {1,2,3} in order. Or, you may choose to use zero-indexed {0,1,2}.

Output

Their Levi-Civita function value from {-1,0,1}. This is code golf.

Test cases

There are 27 possible inputs.

(1, 1, 1) => 0
(1, 1, 2) => 0
(1, 1, 3) => 0
(1, 2, 1) => 0
(1, 2, 2) => 0
(1, 2, 3) => 1
(1, 3, 1) => 0
(1, 3, 2) => -1
(1, 3, 3) => 0
(2, 1, 1) => 0
(2, 1, 2) => 0
(2, 1, 3) => -1
(2, 2, 1) => 0
(2, 2, 2) => 0
(2, 2, 3) => 0
(2, 3, 1) => 1
(2, 3, 2) => 0
(2, 3, 3) => 0
(3, 1, 1) => 0
(3, 1, 2) => 1
(3, 1, 3) => 0
(3, 2, 1) => -1
(3, 2, 2) => 0
(3, 2, 3) => 0
(3, 3, 1) => 0
(3, 3, 2) => 0
(3, 3, 3) => 0
\$\endgroup\$
1

21 Answers 21

23
\$\begingroup\$

Jelly, 5 bytes

ṁ4IṠS

Try it online!

Algorithm

Let's consider the differences j-i, k-j, i-k.

  • If (i, j, k) is a rotation of (1, 2, 3), the differences are a rotation of (1, 1, -2). Taking the sum of the signs, we get 1 + 1 + (-1) = 1.

  • If (i, j, k) is a rotation of (3, 2, 1), the differences are a rotation of (-1, -1, 2). Taking the sum of the signs, we get (-1) + (-1) + 1 = -1.

  • For (i, i, j) (or a rotation), where i and j may be equal, the differences are (0, j-i, i-j). The signs of j-i and i-j are opposite, so the sum of the signs is 0 + 0 = 0.

Code

ṁ4IṠS  Main link. Argument: [i, j, k]

ṁ4     Mold 4; yield [i, j, k, i].
  I    Increments; yield [j-i, k-j, i-k].
   Ṡ   Take the signs, replacing 2 and -2 with 1 and -1 (resp.).
    S  Take the sum.
\$\endgroup\$
1
  • \$\begingroup\$ Beautiful--surely this was xnor's intended algorithm. \$\endgroup\$ Mar 27, 2018 at 0:24
11
\$\begingroup\$

Python 2, 32 bytes

lambda i,j,k:(i-j)*(j-k)*(k-i)/2

Try it online!

Algorithm

Let's consider the differences i-j, j-k, k-i.

  • If (i, j, k) is a rotation of (1, 2, 3), the differences are a rotation of (-1, -1, 2). Taking the product, we get (-1) × (-1) × 2 = 2.

  • If (i, j, k) is a rotation of (3, 2, 1), the differences are a rotation of (1, 1, -2). Taking the product, we get 1 × 1 × (-2) = -2.

  • For (i, i, j) (or a rotation), where i and j may be equal, the differences are (0, i-j, j-i). Taking the product, we get 0 × (i-j) × (j-i) = 0.

Thus, dividing the product of the differences by 2 yields the desired result.

\$\endgroup\$
7
\$\begingroup\$

x86, 15 bytes

Takes arguments in %al, %dl, %bl, returns in %al. Straightforward implementation using Dennis's formula.

 6: 88 c1                   mov    %al,%cl
 8: 28 d0                   sub    %dl,%al
 a: 28 da                   sub    %bl,%dl
 c: 28 cb                   sub    %cl,%bl
 e: f6 e3                   mul    %bl
10: f6 e2                   mul    %dl
12: d0 f8                   sar    %al
14: c3                      retq 

Aside: I think I understand why %eax is the "accumulator" now...

\$\endgroup\$
2
  • \$\begingroup\$ I think you meant sar not shr. \$\endgroup\$
    – Jester
    Mar 28, 2018 at 13:08
  • \$\begingroup\$ @Jester good catch. fixed \$\endgroup\$
    – qwr
    Mar 28, 2018 at 15:21
6
\$\begingroup\$

Octave, 20 bytes

@(v)det(eye(3)(:,v))

Pretty direct implementation of the determinant formula. Permutes the columns of the identity matrix then takes the determinant.

\$\endgroup\$
6
\$\begingroup\$

Wolfram Language (Mathematica), 9 bytes

Signature

Try it online!


Wolfram Language (Mathematica), 18 bytes

Saved 2 bytes thanks to Martin Ender.

Det@{#^0,#,#^2}/2&

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ builtins are no fun \$\endgroup\$
    – qwr
    Mar 27, 2018 at 5:56
  • 2
    \$\begingroup\$ The Vandermonde determinant is nice. There's also Det@IdentityMatrix[3][[#]]& (longer, but fewer tokens). \$\endgroup\$ Mar 27, 2018 at 18:48
  • 1
    \$\begingroup\$ #^1 is just # ;) \$\endgroup\$ Mar 28, 2018 at 10:55
5
\$\begingroup\$

Haskell, 26 bytes

(x#y)z=(x-y)*(y-z)*(z-x)/2

Try it online!

Nasty IEEE floats...

\$\endgroup\$
4
\$\begingroup\$

JavaScript (ES6), 38 bytes

Overcomplicated but fun:

(a,b,c,k=(a+b*7+c*13)%18)=>k-12?+!k:-1

Try it online!


JavaScript (ES6), 28 bytes

Using the standard formula:

(a,b,c)=>(a-b)*(b-c)*(c-a)/2

Try it online!

\$\endgroup\$
4
\$\begingroup\$

05AB1E, 7 5 bytes

1 byte saved thanks to @Emigna

ĆR¥P;

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Ć instead of 4∍ saves a byte. \$\endgroup\$
    – Emigna
    Mar 27, 2018 at 8:36
4
\$\begingroup\$

APL (Dyalog), 11 9 bytes

2 bytes saved thanks to @ngn

+/×2-/4⍴⎕

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ as a complete program it's 9 bytes: +/×2-/4⍴⎕ \$\endgroup\$
    – ngn
    Mar 28, 2018 at 16:10
3
\$\begingroup\$

Ruby, 28 bytes

->a,b,c{(a-b)*(b-c)*(c-a)/2}

Try it online!

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

CJam (16 bytes)

1q~{)1$f-@+:*\}h

Online demo. Note that this is based on a previous answer of mine which uses the Levi-Civita symbol to calculate the Jacobi symbol.

\$\endgroup\$
1
\$\begingroup\$

Ruby, 56 bytes

->t{t.uniq!? 0:(0..2).any?{|r|t.sort==t.rotate(r)}?1:-1}

Try it online!

Once we rule out cases where the values of the triplet are not unique, t.sort is equivalent to (and shorter than) [1,2,3] or [*1..3]

->t{
  t.uniq! ? 0                     # If applying uniq modifies the input, return 0
          : (0..2).any?{|r|       # Check r from 0 to 2:
              t.sort==t.rotate(r) #   If rotating the input r times gives [1,2,3],
            } ? 1                 #     return 1;
              :-1                 #     else return -1
}
\$\endgroup\$
1
\$\begingroup\$

Husk, 7 bytes

ṁ±Ẋ-S:←

Try it online!

Explanation

Straight port of Dennis's Jelly answer. S:← copies the head of the list to the end, Ẋ- takes adjacent differences, and ṁ± takes the sign of each element and sums the result.

\$\endgroup\$
0
\$\begingroup\$

Jelly, 8 bytes

⁼QȧIḂÐfḢ

Try it online!

Seems too ungolfed. :(

\$\endgroup\$
0
\$\begingroup\$

Add++, 13 bytes

L,@dV@GÑ_@€?s

Try it online!

\$\endgroup\$
0
\$\begingroup\$

SHELL, 44 Bytes

 F(){ bc<<<\($2-$1\)*\($3-$1\)*\($3-$2\)/2;}

tests :

 F 1 2 3
 1

 F 1 1 2
 0

 F  2 3 1
 1

 F 3 1 2
 1

 F 3 2 1
 -1

 F 2 1 3
 -1

 F 1 3 2
 -1

 F 1 3 1
 0

Explanation :

 The formula is : ((j - i)*(k - i)*(k - j))/2

BC, 42 Bytes

 define f(i,j,k){return(j-i)*(k-i)*(k-j)/2}

tests:

 f(3,2,1)
 -1
 f(1,2,3)
 1
 f(1,2,1)
 0
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Is it possible just to claim the language as bc to avoid the extraneous call/function declaration? \$\endgroup\$ Mar 27, 2018 at 0:10
  • 1
    \$\begingroup\$ In which shell does this work? \$\endgroup\$
    – Dennis
    Mar 27, 2018 at 1:30
0
\$\begingroup\$

Stax, 8 bytes

äN§lüy²Å

Run and debug it

Translates to -(b-a)(c-b)(a-c)/2.

\$\endgroup\$
0
\$\begingroup\$

J, 12 bytes

1#.2*@-/\4$]

Try it online!

Direct translation of Uriel's APL solution into J.

Explanation:

4$] Extends the list with its first item

2 /\ do the following for all the overlapping pairs in the list:

*@- find the sign of their difference

1#. add up

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I'll leave this Vandermonde-determinant-based solution here as a comment in case anyone can figure out how to golf it down: (-/ .*)@:(^&(i.3)"0)%2: \$\endgroup\$ Mar 27, 2018 at 18:56
0
\$\begingroup\$

Japt, 7 bytes

änUÌ xg

Try it


Explanation

            :Implicit input of array U
ä           :Get each consecutive pair of elements
 n          :Reduce by subtracting the first from the last
  UÌ        :But, before doing that, prepend the last element in U
     g      :Get the signs
    x       :Reduce by addition

Alternative

Takes input as individual integers.

NänW ×z

Try it

\$\endgroup\$
0
\$\begingroup\$

Java 8, 28 bytes

(i,j,k)->(i-j)*(j-k)*(k-i)/2

Port of @Dennis' Python 2 answer.

Try it online.

\$\endgroup\$
0
\$\begingroup\$

Python, 33 bytes

lambda i,j,k:(i^j!=k or-~j-i)%3-1

Try it online!

I tried for a while to beat the product-of-differences approach, but the best I got was 1 byte longer.

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.