52
\$\begingroup\$

In this question at Code Review they tried to find the fastest way to return the unique element in an array where all the elements are the same except one. But what is the shortest code that accomplish the same thing?

Goal

Find the unique element in an array and return it.

Rules

  • The input array will contain only integer, strictly positive numbers, so you can use 0 as the end of the input if your language needs it.
  • The size of the array will be at least 3 and will have a finite size. You can limit the size of the array to any limit your language has.
  • Every element in the array will be the same, except for one which will be different.
  • You must output the value (not the position) of the unique element in any standard format. You can output leading or trailing spaces or newlines.
  • You can take the input array in any accepted format.

Examples

Input                   Output
------------------------------
[ 1, 1, 1, 2, 1, 1 ]      2
[ 3, 5, 5, 5, 5 ]         3
[ 9, 2, 9, 9, 9, 9, 9 ]   2
[ 4, 4, 4, 6 ]            6
[ 5, 8, 8 ]               5
[ 8, 5, 8 ]               5
[ 8, 8, 5 ]               5

Winner

This is , so may the shortest code for each language win!

\$\endgroup\$
7
  • \$\begingroup\$ Do we assume the input array contains a unique element and others are the same? \$\endgroup\$
    – Amessihel
    Commented Jul 28, 2020 at 14:52
  • \$\begingroup\$ @Amessihel yes, you don't need to check that, it is assumed. \$\endgroup\$
    – Charlie
    Commented Jul 28, 2020 at 14:54
  • 8
    \$\begingroup\$ The title feels too long for such a simple operation. Suggested: Odd one out \$\endgroup\$
    – Luis Mendo
    Commented Jul 28, 2020 at 15:05
  • 7
    \$\begingroup\$ @LuisMendo nice title, the thing is that I just wanted to use the same title as the original question at Code Review but changing "fastest" with "shortest". :-) \$\endgroup\$
    – Charlie
    Commented Jul 28, 2020 at 15:08
  • 1
    \$\begingroup\$ Suggest adding testcases [8, 8, 5] and [5, 8, 8] since there isn't one were the last element is unique and 3 element arrays are a corner cases in themselves. \$\endgroup\$
    – Noodle9
    Commented Jul 28, 2020 at 19:19

92 Answers 92

3
\$\begingroup\$

Python 3, 56 39 bytes

lambda x:[i for i in x if x.count(i)<2]

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Lambdafication gives 39 bytes. (Singleton list is a valid output format by default.) \$\endgroup\$
    – Bubbler
    Commented Jul 28, 2020 at 14:36
  • 1
    \$\begingroup\$ You don't need to convert the input to a set, since it doesn't matter how many times you uselessly count the multiple element. \$\endgroup\$
    – Neil
    Commented Jul 28, 2020 at 14:36
3
\$\begingroup\$

Gaia, 2 bytes

C⌡

Not a built-in!

C is "count occurrences in list" and is "find the smallest by".

(the footer is "evaluate" and "call the function above", Gaia doesn't seem to evaluate input by default)

Try it online!

\$\endgroup\$
3
  • 2
    \$\begingroup\$ If Gaia does not evaluate input by default, shouldn't you include that in the answer? Note all the R answers that need to do a scan(). \$\endgroup\$
    – Charlie
    Commented Jul 28, 2020 at 15:25
  • \$\begingroup\$ @Charlie This submission is a function, not a full program (for some reason, Gaia actually calls lines of code functions) \$\endgroup\$ Commented Jul 28, 2020 at 15:27
  • \$\begingroup\$ I typically include the e in my Gaia answers, as I feel it's more correct; e↑ always felt like such a gray area to me. I don't think I would have thought of using for this though, this is pretty neat! \$\endgroup\$
    – Giuseppe
    Commented Jul 28, 2020 at 15:30
3
\$\begingroup\$

Wolfram Language (Mathematica), 27 bytes

Keys@Select[Counts@#,#<2&]&

Try it online!

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

Java (JDK), 62 bytes

int f(int[] a){Arrays.sort(a);return a[0]+a[a.length-1]-a[1];}

Try it online!

Thanks to JollyJoker for correct way.

Original completely own failing dumb#ss solution:

int f(int[] a){Arrays.sort(a);return a[0];}

\$\endgroup\$
5
  • 2
    \$\begingroup\$ Nice try, but fails the 1st test case: on [ 1, 1, 1, 2, 1, 1 ] results 1 instead of the required 2. \$\endgroup\$
    – manatwork
    Commented Jul 29, 2020 at 1:07
  • \$\begingroup\$ a[0]<a[1]?a[0]:a[a.length-1] \$\endgroup\$
    – JollyJoker
    Commented Jul 29, 2020 at 10:26
  • \$\begingroup\$ or a[0]+a[a.length-1]-a[1] \$\endgroup\$
    – JollyJoker
    Commented Jul 29, 2020 at 10:48
  • 1
    \$\begingroup\$ Thanks for the input. Trying to play with the Big Bois always makes me look like an #ss. I guess the "New contributor" tag kind of saved me from rougher comments hehe. \$\endgroup\$
    – brat
    Commented Jul 29, 2020 at 13:41
  • 2
    \$\begingroup\$ Suggest int[]a instead of int[] a \$\endgroup\$
    – ceilingcat
    Commented Jul 30, 2020 at 18:14
3
\$\begingroup\$

PHP, 46 45 bytes

fn($i)=>array_flip(array_count_values($i))[1]

Try it online!

Could maybe be golfed more using a custom solution, but the straightforward one is quite short already: returns the first value that is counted one time. Works with any type of value. If only PHP array functions were not prefixed with array_!

EDIT: saved 1 byte thanks to @640KB now uses array_flip, meaning that it still works for any value type but this time gets the last value counted one time

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Yes, darn those long and redundant function names. Turns out it's 45 bytes if you use array_flip() instead of array_search() though! \$\endgroup\$
    – 640KB
    Commented Jul 29, 2020 at 13:27
  • \$\begingroup\$ @640KB nice one! I actually didn't know about array_flip, makes sense! \$\endgroup\$
    – Kaddath
    Commented Jul 29, 2020 at 13:53
3
\$\begingroup\$

Excel, 14 bytes

Put the numbers in column A, and enter this formula in another column

=UNIQUE(A:A,,1
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Per the community meta, you can actually drop the trailing ) for -1 byte as excel will auto correct it to be there for you :) \$\endgroup\$ Commented Jul 30, 2020 at 18:11
  • 1
    \$\begingroup\$ Huh, I somehow forgot/didn't know about UNIQUE() when I did this one. Anyway, you can replace TRUE with 1. \$\endgroup\$ Commented Jul 30, 2020 at 23:06
  • \$\begingroup\$ @Calculuswhiz good point, thanks. Lol I typed this on my phone so I didn’t even test it first. \$\endgroup\$ Commented Jul 30, 2020 at 23:14
3
\$\begingroup\$

C (gcc), 39 bytes

f(int*a){a=*a-*++a?a[*a--!=a[2]]:f(a);}

Try it online!

f(int*a){      // function taking a 0-terminated array pointer.

 a=            // return using eax register trick.
 *a-*++a?      // compare current item with next item :
 a[*a--!=a[2]] // if different we move the pointer by the result of comparing the next item,
:f(a);         // if not we recursively call on the incremented pointer.
}
\$\endgroup\$
3
\$\begingroup\$

C GCC, 40 bytes

f(int*a){a=*a^*++a?a[-(*a==a[1])]:f(a);}

Try it online!

Thanks to xibu for -5 bytes!

Thanks to ceilingcat for -2 bytes!

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

Arn, 12 bytes

BØ├┤ÅöÀ&iG£3

Explanation

Unpacked: $v{(${=v})#<2}

$ Filter
  v{ block with index named v
    ( Start expression
      $ Filter
        { block with index named _
          =v Is current item equal to v
        }
    )
    # Length
    <2 Is less than 2
  }

Output implicit, input on one line split by spaces

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

Ruby 2.7, 15 bytes

p$*.tally.key 1

Takes in the array of chars as input from the arguments $* passed to it.


Ruby 2.7, 18 bytes

->a{a.tally.key 1}

The following is the screenshot of SoloLearn code playground, which uses Ruby 2.7,

enter image description here

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

C (gcc), 48 46 44 bytes

-2 thanks to @ceilingcat

f(int*a){*a=*a-a[-1]?a[-(*a==a[1])]:f(a+1);}

Try it online!

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

Zsh, 22 bytes

<<<${@:#${${(o)@}[2]}}

Try it online!

:#Removes all elements matching the [2]nd element of the (o)rdered array, and <<<prints.

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

Rust, 45 bytes

A closure that takes a mutable slice and returns the outlier.

|s:&mut[u8]|{s.sort();s[0]^s[1]^s[s.len()-1]}

Attempt This Online!

Explanation:

|s:&mut[u8]|{ // Take a mutable slice
  s.sort();   // Sort the slice. This means that
              // the outlier is now either the first or last
              // element, and every element in between must be common. 
  s[0]^s[1]^s[s.len()-1]
  // Since the slice must have at least three elements,
  // the first, second and last number must have distinct indices. 
  // One of these three is the outlier, and the other two are equal.
  // Xoring two equal numbers yields zero, and xoring zero with a
  // number n yields n. The operation is commutative and associative. 
  // Thus, by xoring the three relevant numbers we obtain the outlier. 

  // We could have also subtracted the second element since we know
  // it can't be the outliner, but this both looks less cool
  // and gives overflow problems when not using signed integers.
}
\$\endgroup\$
3
\$\begingroup\$

Desmos, 169 105 37 25 bytes

-12 bytes thanks to @Yousername

f(l)=l.max+l.min-l.median

Try it on Desmos!

\$\endgroup\$
2
  • \$\begingroup\$ 25 bytes: f(x)=x.min+x.max-x.median \$\endgroup\$
    – Yousername
    Commented Jan 4 at 17:54
  • \$\begingroup\$ @Yousername median is smart \$\endgroup\$
    – Aiden Chow
    Commented Jan 4 at 22:03
2
\$\begingroup\$

Charcoal, 8 bytes

IΦθ⁼¹№θι

Try it online! Link is to verbose version of code. Works by filtering out elements whose count is not 1. (Singleton list output is allowed by default, although Charcoal's output for a singleton list looks like that of a bare string anyway.) Explanation:

  θ         Input list
 Φ          Filtered where
     №      Count of
       ι    Current element
      θ     In input list
   ⁼¹       Equals literal `1`
I           Cast to string
            Implicitly print
\$\endgroup\$
2
\$\begingroup\$

R, 36 bytes

n=scan();while(sd(n[-T]))T=T+1;n[+T]

Try it online!

Iterates over the indices, calculating the standard deviation of the array with the associated element removed; when the standard deviation is 0, the removed element is the unique value.

This isn't the shortest by a long shot, but it's a neat little R approach.

\$\endgroup\$
1
  • \$\begingroup\$ It's being a wild R battle, but this is a nice idea. :-) \$\endgroup\$
    – Charlie
    Commented Jul 28, 2020 at 15:11
2
\$\begingroup\$

R, 30 29 bytes

Edit: -1 byte thanks to Giuseppe, but still a long way to go to catch the current leading R solution...

y=table(scan());names(y[y<2])

Try it online!

Outputs a character string containing the value of the lonely element.

Edit: just realized that this is a worse version of the solution that Robin Ryder already discarded...

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

Japt, 4 bytes

ü l1

Try it

Groups (and sorts) by value and then filters items of length 1.

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

MY, 17 bytes

ωω9Ġ'ƒ⇷(⍉Σ1=⍸ω@⍰←

Try it online!

Explanation

ωω9Ġ'ƒ⇷(⍉Σ1=⍸ω@⍰←
ωω                  push the argument twice
  9Ġ'               push "=" in the codepage
     ƒ              turn it into a function
      ⇷             keeping the left argument the same, and mapping over each element 
       (            apply that
        ⍉           transpose
         Σ          sum (now we have how many times each element occurs)
          1=        whether the elements are 1
            ⍸       the indeces of that
             ω@     the actual element
               ⍰    it's in an array, so pick a random element from it (since theres only one)
                ←   output
\$\endgroup\$
2
\$\begingroup\$

Retina, 26 25 bytes

.+
*
O`
,A2,-2`
+`_¶_
¶
_

Try it online! Link includes test suite that converts from a comma-separated list to a newline-separated list for ease of use. Uses @xnor's algorithm. Edit: Saved 1 byte thanks to @FryAmTheEggman pointing out that I didn't need to remove the newlines before counting the _s. Explanation:

.+
*

Convert to unary.

O`

Sort.

,A2,-2`

Drop all entries except the first two and the last.

+`_¶_
¶

Subtract the second value from the sum of the first and last. Well, sort of. All this guarantees is that there are no _s left in between the newlines, so the number of remaining _s is the desired result, but without actually specifying where they are.

_

Count the remaining _s as a decimal integer.

\$\endgroup\$
2
  • \$\begingroup\$ I think you can save a byte doing the subtraction with a loop replacing _¶_ with . I tried to save bytes by making the list always 3 elements by using deduplicate stages, but it didn't work out. \$\endgroup\$ Commented Jul 28, 2020 at 19:41
  • \$\begingroup\$ @FryAmTheEggman Thanks; for some reason I thought I had to delete the s... \$\endgroup\$
    – Neil
    Commented Jul 29, 2020 at 1:25
2
\$\begingroup\$

Retina 0.8.2, 17 bytes

O`
^(.*¶)\1+

1G`

Try it online! Link includes test suite that converts from a comma-separated list to a newline-separated list for ease of use. Explanation:

O`

Sort the input lines so that the unique line is now either first or last.

^(.*¶)\1+

If the first two lines are identical then remove them and all following identical lines.

1G`

Take the first remaining line.

\$\endgroup\$
1
  • \$\begingroup\$ Very nice! I had held off posting for a while because I felt like I was missing something, glad to see there was something better out there after all :) \$\endgroup\$ Commented Jul 29, 2020 at 1:57
2
\$\begingroup\$

C (gcc), 68 \$\cdots\$ 59 58 bytes

Saved a byte thanks to ceilingcat!!!

c;d;f(l,n)int*l;{for(c=0;--n;)l[n]-*l?d=n:(c=1);n=l[d*c];}

Try it online!

Inputs a pointer to an array of integers and its length.
Returns the unique element.

How

We initialises a flag, c, to zero and go through all the elements starting at the last through to the second. We use the first element as a test value. When we find an element different from the first we cache its index in d. If an element is the same as the first, we set c to one. After looping we know that the first element is unique if c is still zero. Otherwise d is the index of the unique element.

\$\endgroup\$
1
  • \$\begingroup\$ @ceilingcat Interesting how the extra braces are worth it - thanks! :-) \$\endgroup\$
    – Noodle9
    Commented Jul 29, 2020 at 8:45
2
\$\begingroup\$

Io, 38 bytes

method(x,x unique sum-x average round)

Try it online!

Explanation

                                       // x = [1,1,2,1,1,1]
method(x,                            )
         x unique                      // Uniquified x: [1,2]
                  sum                  // Sum:          3
                      x average        // Average of x: 1.1666666666666667
                                round  // Round to the closest integer: 1
                     -                 // Minus: 3-1 = 2

Io, 44 bytes

The built-in solution.

method(x,x uniqueCount map(reverse)min last)

Try it online!

Explanation

                                             // e.g. x = [1,2,1,1,1,1]
method(x,                                  ) // Method (taking x):
         x uniqueCount                       // Uniquified counts.   [[1,5],[2,1]]
                       map(reverse)          // Put counts in front. [[5,1],[1,2]]
                                   min       // The one with the smallest count. [1,2]
                                       last  // Return the current item. 2

Io, 44 bytes

(Comparison answer, if I just ported Arnauld's solution anyway)

method(x,x sortInPlace()first+x pop-x at(1))

Try it online!

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

Assembly (as, x64, Linux), 142 bytes (455 bytes code)

This runs on Linux only (for the syscalls) and only respects integers as bytes (input in ASCII).

.intel_syntax noprefix
.text
.global _start
_start:
mov cx,0
r:
lea rbx,a
lea rsi,i
mov rdi,0
mov rdx,2
mov rax,0
push rcx
syscall
pop rcx
mov al,[rsi]
cmp cx,0
je s
cmp cx,1
je t
cmp cx,2
je v
cmp al,[rbx]
jne p
jmp w
s:
mov [rbx],al
inc cx
jmp r
t:
inc cx
cmp al,[rbx]
je r
inc rbx
jmp s
v:
cmp al,[rbx]
je r
mov [rbx+1],al
w:
inc rbx
p:
mov rsi,rbx
mov rdx,1
mov rdi,1
mov rax,1
syscall
mov rdi,0
mov rax, 60
syscall
.data
a:
.byte 0,0
i:
.byte 0,0,0


Try it online!

\$\endgroup\$
7
  • 1
    \$\begingroup\$ Output seems to be the opposite than expected. For [0 1 0] it returns 0 rather than 1. \$\endgroup\$
    – Charlie
    Commented Jul 28, 2020 at 17:52
  • \$\begingroup\$ I also saw this on tio but it actually works on my computer. Nevertheless I linked tio to at least make the rest triable :-( \$\endgroup\$
    – Gedobbles
    Commented Jul 28, 2020 at 17:54
  • 1
    \$\begingroup\$ Functionality aside, you can compact the code by removing newlines here and there (labels can share a line with a mnemonic). Also, mov [rbx+1],al inc rbx can be changed to inc rbx mov [rbx],al. 438 bytes \$\endgroup\$
    – gastropner
    Commented Jul 28, 2020 at 18:31
  • 1
    \$\begingroup\$ x86 answers can be scored by their assembled byte count. codegolf.meta.stackexchange.com/questions/12339/… \$\endgroup\$
    – qwr
    Commented Jul 29, 2020 at 6:03
  • \$\begingroup\$ Thanks for the hint, I'll correct that as soon as I'm not on mobile. \$\endgroup\$
    – Gedobbles
    Commented Jul 29, 2020 at 8:25
2
\$\begingroup\$

Python 2, 47 bytes

i=sorted(input())
print(i[0],i[-1])[i[0]==i[1]]

Try it online!

A long way from the shortest Python answer but just another way of doing it.

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

Dyalog APL, 15 14 bytes

{⍵[⊃⍋+/⍵∘.=⍵]}

-1 byte thanks to @streetster

Try it online!

Explanation

{⍵[⊃⍋+/⍵∘.=⍵]} 
     +/⍵∘.=⍵  - a list of the number of occurences of each element
   ⊃⍋         - grab the first index
 ⍵[         ] - extract that element
\$\endgroup\$
4
  • \$\begingroup\$ Can you add an explanation to the solution? Is there any part of my k solution that can help to golf this? \$\endgroup\$
    – mkst
    Commented Jul 28, 2020 at 20:16
  • 1
    \$\begingroup\$ I don't think there's any part of the K solution that will help, but I will surely add an explanation! \$\endgroup\$
    – Ada
    Commented Jul 28, 2020 at 20:49
  • 1
    \$\begingroup\$ Can you use 'grade up' to get something like this K solution? {x@*<+/x=\:x} - rather than checking for equality with 1, get indices to sort ascending and take the first? \$\endgroup\$
    – mkst
    Commented Jul 29, 2020 at 8:13
  • \$\begingroup\$ Tacit form: ⊢⊃⍨∘⊃∘⍋1⊥∘.=⍨ (TIO) Not so pretty, but saves a byte. \$\endgroup\$
    – Bubbler
    Commented Jul 30, 2020 at 2:14
2
\$\begingroup\$

C (gcc), 50 42 bytes

f(int*b,int*e){b=(*b^*e--?:f(b,e)^*e)^*e;}

Try it online!

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

Brain-Flak, 112 bytes

(()){{}({}<{({}<>)<>}<>>){({}<>)<>}<>(({}[({})])<({}({}))>)((){[()]<{{}({}<(({}[({})])<({}{})>)<>{}>)<>}>}{})}<>

Try it online!

Explanation

Very broadly speaking this cycles the list until the first two elements are unequal. Then it deletes the front element until the second two elements are the same. Once that is done it outputs whatever is on the front.

Ok that wasn't quite true. I said

Then it deletes the front element until the second two elements are the same

But it actually deletes the 1st and the 3rd elements until ...

This doesn't actually make a difference to the output though, to see why let's look at the cases. First the easy cases with more than 3 elements

b a a a a ...

In this case the second two elements are equal (a = a) so it stops and outputs b.

a b a a a ...

In this case the second two elements are unequal (a /= b) so it removes the first and third elements.

b a a ...

Now we are back to the first case.

Now for the cases with three elements.

b a a

In this case the second two elements are equal (a = a) so it stops and outputs b.

a b a

In this case the second two elements are unequal (a /= b) so it removes the first and third elements.

b

Now we want to run the check again, but there is only one element. Luckily Brain-Flak pads the bottom of the stack with zeros so this is really the same as

b 0 0

And we assumed input was positive b /= 0 so we are back to the case above.


So that works fine but why do we do it?

The thing about Brain-flak is that in order to do any non trivial checks with an element we need to pop it from the stack. That means that if we want to do things in place, like check if one element is equal to another, we need to pop those things and put them back. So here we save bytes by not putting the third element back when we are checking equality.

This saves us two bytes.

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

Lua, 43 bytes

t=arg table.sort(t)print(t[1]+t[#t]-t[2]|0)

Try it online!

Returning method stolen from Arnauld's solution.

Alternate Solution, 49 Bytes:

t=arg table.sort(t)print(t[t[1]<t[2]and 1or#t]|0)

Notes

Lua's table indexing starts at 1, and boolean logic generally returns the value rather than an actual bool.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ -1: snippets are not allowed. In JS answer you are referring to a function is declared and a is a name of its argument. This is not the case for your answer, which does not declare callable function and uses variables for input and output, which is not allowed as well. \$\endgroup\$ Commented Jul 31, 2020 at 11:21
  • 1
    \$\begingroup\$ Sorry, was not familiar with the rules when I first started. Fixed to make it a full program. \$\endgroup\$
    – Benrob0329
    Commented Jul 31, 2020 at 16:45
  • 1
    \$\begingroup\$ Great! Turned -1 into +1 now. Also, just learnt that |0 can be used to convert numbers to integers (I knew about //1, but this is new for me). P.S.: it's recommended to use tio.run to provide examples. It also provides code in format that can be directly copied as a Codegolf.SE answer. \$\endgroup\$ Commented Jul 31, 2020 at 17:19
2
\$\begingroup\$

Python 3, 49 bytes

def f(n):n.sort();return (n[0],n[-1])[n[0]==n[1]]

Try it online!

\$\endgroup\$
4
  • \$\begingroup\$ Why are you sorting the input outside your code? (you may not assume the input is sorted because there are test cases where it is not) Also, this does not work correctly even for the test case included in your TIO link... \$\endgroup\$ Commented Aug 9, 2020 at 16:39
  • \$\begingroup\$ @my pronoun is monicareinstate Thank you, for mentioning my blunder, and i corrected the code \$\endgroup\$
    – Eesa
    Commented Aug 9, 2020 at 17:50
  • \$\begingroup\$ The second option is wrong. This still doesn't work: Try it online! \$\endgroup\$ Commented Aug 10, 2020 at 2:49
  • \$\begingroup\$ @mypronounismonicareinstate sorry, I oversight it. Edited the code, now it works perfect \$\endgroup\$
    – Eesa
    Commented Aug 10, 2020 at 7:37

Your Answer

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

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