41
\$\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
    Jul 28, 2020 at 14:52
  • \$\begingroup\$ @Amessihel yes, you don't need to check that, it is assumed. \$\endgroup\$
    – Charlie
    Jul 28, 2020 at 14:54
  • 7
    \$\begingroup\$ The title feels too long for such a simple operation. Suggested: Odd one out \$\endgroup\$
    – Luis Mendo
    Jul 28, 2020 at 15:05
  • 5
    \$\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
    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
    Jul 28, 2020 at 19:19

68 Answers 68

3
\$\begingroup\$

Husk, 3 2 bytes

-1 byte thanks to Razetime!

◄=

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ 2 bytes \$\endgroup\$
    – Razetime
    Oct 15, 2020 at 5:47
2
\$\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
    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
    Jul 28, 2020 at 14:36
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
    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\$ Jul 28, 2020 at 19:41
  • \$\begingroup\$ @FryAmTheEggman Thanks; for some reason I thought I had to delete the s... \$\endgroup\$
    – Neil
    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\$ 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
    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
    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
    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
    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
    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
    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\$

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
  • 1
    \$\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
    Jul 29, 2020 at 13:27
  • \$\begingroup\$ @640KB nice one! I actually didn't know about array_flip, makes sense! \$\endgroup\$
    – Kaddath
    Jul 29, 2020 at 13:53
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
    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
    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
    Jul 29, 2020 at 8:13
  • \$\begingroup\$ Tacit form: ⊢⊃⍨∘⊃∘⍋1⊥∘.=⍨ (TIO) Not so pretty, but saves a byte. \$\endgroup\$
    – Bubbler
    Jul 30, 2020 at 2:14
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\$ 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
    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\$ 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\$ Aug 9, 2020 at 16:39
  • \$\begingroup\$ @my pronoun is monicareinstate Thank you, for mentioning my blunder, and i corrected the code \$\endgroup\$
    – Eesa
    Aug 9, 2020 at 17:50
  • \$\begingroup\$ The second option is wrong. This still doesn't work: Try it online! \$\endgroup\$ Aug 10, 2020 at 2:49
  • \$\begingroup\$ @mypronounismonicareinstate sorry, I oversight it. Edited the code, now it works perfect \$\endgroup\$
    – Eesa
    Aug 10, 2020 at 7:37
2
\$\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
2
\$\begingroup\$

JavaScript (61 60 bytes)

My first attempt in this community, so there's room for improvement:
x=>{[a,b,c]=x.filter((e,i)=>x[i-1]!=e);return !c&&x[1]-a?a:b}

x=>{[a,b,c]=x.filter((e,i)=>x[i-1]!=e);return!c&&x[1]-a?a:b}

Try it online!

Explanation:

x.filter((e,i)=>x[i-1]!=e)

The array is filtered to remove any element that is the same as array[index - 1]. These are then unpacked into variables [a,b,c].
The three scenarios are 1) [same, unique, same] 2) [unique, same] 3) [same, unique]

return !c&&x[1]-a?a:b

If c is undefined, i.e. the unique element was on the end of the array - and if 'a' (which is by now either array[0] or array[last element - 1]) is not equal to array[1], then a is the unique element. Otherwise, we have scenario 1 or 3, either way - return 'b'

\$\endgroup\$
3
  • \$\begingroup\$ Welcome to the wonderful world of code golf! I look forward to seeing more of your posts! \$\endgroup\$
    – lyxal
    Aug 13, 2020 at 23:56
  • \$\begingroup\$ Also, -1 byte by removing the space between return and ! \$\endgroup\$
    – lyxal
    Aug 13, 2020 at 23:57
  • \$\begingroup\$ Thanks, not sure how I missed that whitespace lol. \$\endgroup\$
    – Scott
    Aug 15, 2020 at 1:22
2
\$\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
2
\$\begingroup\$

Vyxal, 3 bytes

Ċ↓h

Try it Online!

Explained

Ċ↓h
Ċ     # Get the counts of all items
 ↓    # Get the smallest item based on last item
  h   # Output the head of that list

Also, according to code-golf's statistics, only a small percentage of people who view my answers actually upvote them. So if you enjoy this answer, consider upvoting, it's free, and you can change your mind at any time (given you have ≥2k rep). Enjoy the answer.

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

Desmos, 169 105 37 bytes

f(a)=b[1]+b[length(a)]-b[2]
b=sort(a)

Try it on Desmos!

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

Wolfram Language (Mathematica) 17 29 28 bytes

Code corrected due to comment by @att:

SortBy[Tally[#],Last][[1,1]]&

theorist managed to shave off one byte with this:

Cases[Tally@#,{_,1}][[1,1]]&
\$\endgroup\$
3
  • 3
    \$\begingroup\$ Fails when the unique element is the first element. \$\endgroup\$
    – att
    Jul 28, 2020 at 19:22
  • \$\begingroup\$ Yes, Good catch! (I corrected the code.) \$\endgroup\$
    – DavidC
    Jul 29, 2020 at 15:04
  • \$\begingroup\$ Also (saves 1 byte): Cases[Tally@#,{_,1}][[1,1]]& \$\endgroup\$
    – theorist
    Jun 20, 2021 at 21:55
1
\$\begingroup\$

Perl 5 -a, 33 bytes

1-(@b="@F"=~/\b$_\b/g)||say for@F

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Note that in the input every element must be the same except one, so [1 2 3 4 4 3 1 1] would not be a valid input. \$\endgroup\$
    – Charlie
    Jul 28, 2020 at 14:26
  • \$\begingroup\$ Changed my test case, but it doesn't really matter to the code. It finds the unique element either way. \$\endgroup\$
    – Xcali
    Jul 28, 2020 at 14:34
1
\$\begingroup\$

Japt -m, 4 bytes

ü l1

Try it

ü       sort and group
  l1    take lenght 1 result
\$\endgroup\$
1
\$\begingroup\$

Retina, 24 bytes

N`
L0`^(\d+)(?!¶\1)|\d+$

Try it online!

This works by sorting the input (one number per line) and then outputting the first number if it is different from the second, and otherwise outputting the last number.

The test case code was taken from Neil's Retina answer which uses an arithmetic method to determine the answer after sorting.

\$\endgroup\$
1
  • \$\begingroup\$ You inspired me to write an answer which could be backported to Retina 0.8.2, and was shorter to boot! \$\endgroup\$
    – Neil
    Jul 29, 2020 at 1:51
1
\$\begingroup\$

Google Sheets, 28

Closing parens already discounted.

  • Column A is input.
  • B1 - =SORT(A:A)
  • B2 - =FILTER(B:B,B:B<>B2)

Excel 2016, 35

  • Column A is input.
  • B1 - =MAX(A:A)
  • B2 - =IF(MODE(A:A)-B1,B1,MIN(A:A))

If the mode is the same as the max, then it's the min, otherwise max.

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

Burlesque, 8 bytes

psf:<][~

Try it online!

Explanation:

ps       # Parse input string as a block
  f:     # Frequency list - returns block of blocks with format {frequency value}
    <]   # Take the minimum block, in this case calculated based on the first element (frequency)
      [~ # Take the last element (value)
         # Implicitly output
\$\endgroup\$
1
\$\begingroup\$

C# 42 Bytes

r.GroupBy(a=>a).First(a=>a.Count()==1).Key
\$\endgroup\$
3
  • \$\begingroup\$ Welcome to the site. Are you sure C# requires all that whitespace? If it doesn't, removing it could be a easy way to shorten this. \$\endgroup\$
    – Wheat Wizard
    Jul 30, 2020 at 2:36
  • \$\begingroup\$ @AdHocGarfHunter Thanks! You're right. Have edited it further \$\endgroup\$
    – primmslim
    Jul 30, 2020 at 2:56
  • 1
    \$\begingroup\$ Also if I understand the code correctly groups can't be size zero? So <2 should be a shorter way of checking ==1. If you want tips for golfing in C# from someone who actually knows C# we have a tips page for the language. \$\endgroup\$
    – Wheat Wizard
    Jul 30, 2020 at 3:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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