Levi-Civita symbol

29

0

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

xnor

Posted 2018-03-26T22:02:35.387

Reputation: 115 687

2Related. – Martin Ender – 2018-03-26T22:24:26.977

Answers

20

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.

Dennis

Posted 2018-03-26T22:02:35.387

Reputation: 196 637

Beautiful--surely this was xnor's intended algorithm. – ETHproductions – 2018-03-27T00:24:47.157

8

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.

Dennis

Posted 2018-03-26T22:02:35.387

Reputation: 196 637

7

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

qwr

Posted 2018-03-26T22:02:35.387

Reputation: 8 929

I think you meant sar not shr. – Jester – 2018-03-28T13:08:56.440

@Jester good catch. fixed – qwr – 2018-03-28T15:21:19.420

6

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.

Nick Alger

Posted 2018-03-26T22:02:35.387

Reputation: 376

5

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!

alephalpha

Posted 2018-03-26T22:02:35.387

Reputation: 23 988

builtins are no fun – qwr – 2018-03-27T05:56:31.917

2The Vandermonde determinant is nice. There's also Det@IdentityMatrix[3][[#]]& (longer, but fewer tokens). – Kyle Miller – 2018-03-27T18:48:10.273

1#^1 is just # ;) – Martin Ender – 2018-03-28T10:55:06.390

4

APL (Dyalog), 11 9 bytes

2 bytes saved thanks to @ngn

+/×2-/4⍴⎕

Try it online!

Uriel

Posted 2018-03-26T22:02:35.387

Reputation: 11 708

as a complete program it's 9 bytes: +/×2-/4⍴⎕ – ngn – 2018-03-28T16:10:01.390

4

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!

Arnauld

Posted 2018-03-26T22:02:35.387

Reputation: 111 334

4

05AB1E, 7 5 bytes

1 byte saved thanks to @Emigna

ĆR¥P;

Try it online!

Uriel

Posted 2018-03-26T22:02:35.387

Reputation: 11 708

Ć instead of 4∍ saves a byte. – Emigna – 2018-03-27T08:36:27.540

4

Haskell, 26 bytes

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

Try it online!

Nasty IEEE floats...

totallyhuman

Posted 2018-03-26T22:02:35.387

Reputation: 15 378

3

Ruby, 28 bytes

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

Try it online!

Level River St

Posted 2018-03-26T22:02:35.387

Reputation: 22 049

2

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.

Peter Taylor

Posted 2018-03-26T22:02:35.387

Reputation: 41 901

1

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
}

benj2240

Posted 2018-03-26T22:02:35.387

Reputation: 801

1

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.

Sophia Lechner

Posted 2018-03-26T22:02:35.387

Reputation: 1 200

0

Jelly, 8 bytes

⁼QȧIḂÐfḢ

Try it online!

Seems too ungolfed. :(

Erik the Outgolfer

Posted 2018-03-26T22:02:35.387

Reputation: 38 134

0

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

Ali ISSA

Posted 2018-03-26T22:02:35.387

Reputation: 211

1Is it possible just to claim the language as bc to avoid the extraneous call/function declaration? – caird coinheringaahing – 2018-03-27T00:10:25.667

1In which shell does this work? – Dennis – 2018-03-27T01:30:53.467

0

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

Shaggy

Posted 2018-03-26T22:02:35.387

Reputation: 24 623

0

Add++, 13 bytes

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

Try it online!

caird coinheringaahing

Posted 2018-03-26T22:02:35.387

Reputation: 13 702

0

Stax, 8 bytes

äN§lüy²Å

Run and debug it

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

Weijun Zhou

Posted 2018-03-26T22:02:35.387

Reputation: 3 396

0

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

Galen Ivanov

Posted 2018-03-26T22:02:35.387

Reputation: 13 815

1I'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: – Kyle Miller – 2018-03-27T18:56:53.873

0

Java 8, 28 bytes

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

Port of @Dennis' Python 2 answer.

Try it online.

Kevin Cruijssen

Posted 2018-03-26T22:02:35.387

Reputation: 67 575

0

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.

xnor

Posted 2018-03-26T22:02:35.387

Reputation: 115 687