This is intended to be an easy, bite-size code-golf.
The mex (minimal excluded number) of a finite collection of numbers is the smallest non-negative integer 0, 1, 2, 3, 4, ...
that does not appear in the collection. In other words, it's the minimum of the complement. The mex operation is central to the analysis of impartial games in combinatorial game theory.
Your goal is to write a program or named function to compute the mex using as few bytes as possible.
Input:
A list of non-negative integers in any order. May contain repeats. For concreteness, the length of the list and the allowed range of elements will both be between 0
and 20
inclusive.
The definition of "list" here is flexible. Any structure that represents a collection of numbers is fine, as long as it has a fixed ordering of elements and allows repeats. It may not include any auxiliary information except its length.
The input can be taken as a function argument or through STDIN.
Output
The smallest excluded number. Output or print it.
Test cases
[1]
0
[0]
1
[2, 0]
1
[3, 1, 0, 1, 3, 3]
2
[]
0
[1, 2, 3]
0
[5, 4, 1, 5, 4, 8, 2, 1, 5, 4, 0, 7, 7]
3
[3, 2, 1, 0]
4
[0, 0, 1, 1, 2, 2, 3]
4
[1, 0, 7, 6, 3, 11, 15, 1, 9, 2, 3, 1, 5, 2, 3, 4, 6, 8, 1, 18]
10
75 Answers 75
Pyth, 6 bytes
h-U21Q
Example run
$ pyth -c h-U21Q <<< '[5, 4, 1, 5, 4, 8, 2, 1, 5, 4, 0, 7, 7]'
3
How it works
U21 range(21)
Q eval(input())
-U21Q setwisedifference(range(21), eval(input)) # Pyth function. Preserves order.
h-U21Q setwisedifference(range(21), eval(input))[0]
-
\$\begingroup\$ When the set is converted to list, is it always in sorted order? \$\endgroup\$xnor– xnor2014年09月30日 03:40:42 +00:00Commented Sep 30, 2014 at 3:40
-
\$\begingroup\$ Pyth's set difference preserves the order of the first argument (
range(21)
), which is ordered. (This also means the explanation isn't entirely accurate. Pyth and Python 3 are both fairly new to me.) \$\endgroup\$Dennis– Dennis2014年09月30日 03:48:36 +00:00Commented Sep 30, 2014 at 3:48 -
1\$\begingroup\$ To clarify,
-
in Pyth is actually a filter - it filters the first argument for absence from the second argument, then converts it to the form of the first argument (string, list or set). \$\endgroup\$izzyg– izzyg2014年10月01日 06:55:22 +00:00Commented Oct 1, 2014 at 6:55 -
\$\begingroup\$ Also, Dennis, it should be
h-U22Q
so it will give the correct output of 21 on the input containing the full allowable range. \$\endgroup\$izzyg– izzyg2014年10月01日 06:57:28 +00:00Commented Oct 1, 2014 at 6:57 -
\$\begingroup\$ @isaacg: The list's length is also limited to 20, so it cannot contain all 21 numbers from 0 to 20. \$\endgroup\$Dennis– Dennis2014年10月01日 13:06:41 +00:00Commented Oct 1, 2014 at 13:06
CJam, (削除) 11 (削除ここまで) 8 bytes
K),l~^1<
How it works:
K), "Create an array with numbers 0 through 20"
l~ "Read the input and eval it, resulting to an array"
^ "XOR the elements of two arrays, resulting in a complement array"
1< "Take the first element of the resultant array"
Sample input:
[1 0 7 6 3 11 15 1 9 2 3 1 5 2 3 4 6 8 1 18]
Output:
10
-
\$\begingroup\$ How high do the single-character numbers in CJam go? \$\endgroup\$xnor– xnor2014年09月29日 21:47:02 +00:00Commented Sep 29, 2014 at 21:47
-
\$\begingroup\$ @xnor Sadly, 20 - sourceforge.net/p/cjam/wiki/Variables \$\endgroup\$Optimizer– Optimizer2014年09月29日 21:48:28 +00:00Commented Sep 29, 2014 at 21:48
-
\$\begingroup\$ A lucky choice! \$\endgroup\$xnor– xnor2014年09月29日 21:50:20 +00:00Commented Sep 29, 2014 at 21:50
J - 13 char
f=:0{i.@21&-.
Very simple actions in J, and thus very hard to make smaller.
i.@21
creates a list from 0 to 20 inclusive. -.
performs set-subtracts the input from this list. 0{
takes the first element of what's left, i.e. the smallest number. f=:
defines a named function. At the REPL:
f=:0{(i.21)&-.
f 1
0
f 0
1
f 2 0
1
f 3 1 0 1 3 3
2
f '' NB. empty list
0
f 1 2 3
0
f 5 4 1 5 4 8 2 1 5 4 0 7 7
3
f 3 2 1 0
4
f 0 0 1 1 2 2 3
4
f 1 0 7 6 3 11 15 1 9 2 3 1 5 2 3 4 6 8 1 18
10
Since the release of J806 in November 2017, a new syntax exists which saves us one byte by letting us use i.@21
for the old (i.21)
in this context.
-
\$\begingroup\$ Do you need
f=:
? \$\endgroup\$Esolanging Fruit– Esolanging Fruit2017年05月02日 00:44:57 +00:00Commented May 2, 2017 at 0:44 -
\$\begingroup\$ Since November 2017
i.@21-.]
would save 1 byte. \$\endgroup\$FrownyFrog– FrownyFrog2018年05月07日 16:26:30 +00:00Commented May 7, 2018 at 16:26
Jelly, (削除) 5 (削除ここまで) 4 bytes
0ḟ1#
Doesn't use the bounds on the input.
...am I missing something?
0 Starting with 0,
1# find the first integer
ḟ which is not in the input.
Brachylog, 4 bytes
N≜¬∈
Works for any list size and any integer magnitudes.
Takes input from the Output variable, and outputs to the Input variable.
Explanation
N We want a non-negative integer
≜ Assign a value such that...
¬∈ ...it is not an element of the list
-
1\$\begingroup\$ Oddly enough, it looks like the
≜
can be dropped going the other way. \$\endgroup\$Unrelated String– Unrelated String2022年09月24日 04:20:25 +00:00Commented Sep 24, 2022 at 4:20 -
\$\begingroup\$ ...Actually, the original version can handle an empty list, while this can't. Whoops \$\endgroup\$Unrelated String– Unrelated String2023年02月26日 14:46:00 +00:00Commented Feb 26, 2023 at 14:46
-
1\$\begingroup\$ @UnrelatedString Reverted. \$\endgroup\$Fatalize– Fatalize2023年02月27日 08:43:20 +00:00Commented Feb 27, 2023 at 8:43
Trilangle, 53 bytes
'0.<_.\.>?0e#L_'\r/(&,円<.|.1.2S<.^#':2',.<..^,円!@.^)S
I'm not convinced this is optimal, but I've thought about it for a while and I don't think I can shrink it without substantial restructuring. I have proven that it's impossible to do this general approach without at least a grid of size n=8, and this is n=10.
Try it on the online interpreter!
Unfolds to this:
'
0 .
< _ .
\ . > ?
0 e # L _
' \ r / ( &
\ , < . | . 1
. 2 S < . ^ # '
: 2 ' , . < . . ^
\ , ! @ . ^ ) S . .
Equivalent to this C code:
#include <stdio.h>
// Read an integer from stdin, throwing out any separators. Returns -1 on EOF.
// Exact implementation is unimportant (and provided by the interpreter).
extern int getint(void);
int main() {
// RED PATH
// Keep a bitfield of the numbers that have been seen so far
int field = 0;
int i;
while ((i = getint()) >= 0)
// GREEN PATH
field |= 1 << i;
// BLUE PATH
// Find the lowest nonzero bit
int missing = 0;
while (field & 1) {
// MAGENTA PATH
field >>= 1;
++missing;
}
// YELLOW PATH
printf("%d\n", missing);
}
I am not doing an instruction-by-instruction walkthrough of this code. If you're interested, you can look into the disassembly feature of the interpreter.
Golfscript 7
~21,^0=
A further-golfed version of Peter Taylor's answer. Community wiki since I don't have the rep to comment on his post.
The difference is using the known max list size from the question instead of length +1 to save a character and dropping the irrelevant $.
-
1\$\begingroup\$ Dammit Golfscript for saving 1 character so as to not read the input -_- \$\endgroup\$Optimizer– Optimizer2014年09月29日 22:01:34 +00:00Commented Sep 29, 2014 at 22:01
Burlesque - 9 Bytes
20rzj\\<]
Takes input from stdin in the format {7 6 5 5 1 2 2 4 2 0}
Explained:
20 rz map a range from 0 to 20. (thanks to algorithmshark for the cocde fix)
j \\ swaps the two arrays, and collects the difference between the two into a new array
<] gets the smallest element of the resulting array.
Try some examples:
-
1\$\begingroup\$ This fails to give any output on the input
{0 1 2}
, because you need torz
one more than the largest number. Just going straight for20rzj\\<]
fixes this and saves a char. \$\endgroup\$algorithmshark– algorithmshark2014年09月30日 17:09:17 +00:00Commented Sep 30, 2014 at 17:09 -
\$\begingroup\$ @algorithmshark No way around it, you are very right. Fixed. And thank you. \$\endgroup\$AndoDaan– AndoDaan2014年09月30日 17:34:18 +00:00Commented Sep 30, 2014 at 17:34
Bash+coreutils, 23 bytes
seq 0 20|egrep -vwm1 1ドル
This assumes input as a |
(pipe) separated list. E.g:
$ ./mex.sh "5|4|1|5|4|8|2|1|5|4|0|7|7"
3
$
-
1\$\begingroup\$ I don't think you need
"(...)"
around the1ドル
. \$\endgroup\$Dennis– Dennis2014年09月30日 16:42:13 +00:00Commented Sep 30, 2014 at 16:42 -
1\$\begingroup\$ Pipe-separated is fine, it meets the list-like condition of the spec. \$\endgroup\$xnor– xnor2014年09月30日 20:35:42 +00:00Commented Sep 30, 2014 at 20:35
-
\$\begingroup\$ If you take input separated by newlines, you can use
grep
instead ofegrep
\$\endgroup\$pxeger– pxeger2023年02月26日 15:25:29 +00:00Commented Feb 26, 2023 at 15:25
Jelly, 7 bytes
Ṁ‘‘Ḷḟ8Ḣ
How it works
Ṁ‘‘Ḷḟ8Ḣ Main Link; argument is z
Ṁ‘‘ Takes 2 above the largest element in z
Ḷ Takes lowered range (thus returning [0, ..., max(z) + 1])
ḟ8 Exclude all elements from the range that are also in z
Ḣ Take the first element (which is the smallest)
Thanks to @LeakyNun for -1 byte!
-
\$\begingroup\$ 1 byte off \$\endgroup\$Leaky Nun– Leaky Nun2017年05月01日 14:25:42 +00:00Commented May 1, 2017 at 14:25
Vyxal gH
, 2 bytes
ʀ⊍
Try it Online! (Includes test cases)
# H flag presets the stack to 100
ʀ # inclusive range 0..100
⊍ # set difference
# g flag takes the minimum of the top of stack after execution
# which is implicitly output
Ruby, 32 bytes
f=->n{(0..20).find{|i|n-[i]==n}}
Defines a function f
to be called with an array.
-
\$\begingroup\$ Any comments from the downvoter? Did I miss some part of the spec? \$\endgroup\$Martin Ender– Martin Ender2014年09月30日 13:19:51 +00:00Commented Sep 30, 2014 at 13:19
-
\$\begingroup\$ I doubt it. Several other answers (including mine) got a mystery downvote. \$\endgroup\$Greg Hewgill– Greg Hewgill2014年09月30日 15:25:46 +00:00Commented Sep 30, 2014 at 15:25
-
\$\begingroup\$ @ipi but it does... in exactly the same format given in the examples in the challenge posts, e.g.
f[[0, 1]]
(where the outer brackets are invocation syntax and the inner brackets define the array). \$\endgroup\$Martin Ender– Martin Ender2014年09月30日 16:07:11 +00:00Commented Sep 30, 2014 at 16:07 -
\$\begingroup\$ Why do you need the
f=
? \$\endgroup\$Esolanging Fruit– Esolanging Fruit2017年05月02日 00:47:24 +00:00Commented May 2, 2017 at 0:47
MathGolf, (削除) 5 (削除ここまで) 4 bytes
Jr,╓
This solution is restricted to just the range 0 to 20, though this can be extended easily by increasing the initial range.
Explanation:
Jr Range from 0 to 20
, Remove elements from the input list from this range
╓ Return the minimum element
Alternatively, a 5 byte solution for all numbers:
Åï╧▲さんかくï
Explanation:
Å ▲さんかく Do while true
╧ Does the input contain
ï The index of the loop?
ï Push the number of iterations of the last loop
-
\$\begingroup\$ With the new changes that are (hopefully) being added to TIO today, there's a 4 byte solution to this problem. It is restricted to an upper limit defined in the code, but since MathGolf has a 1-byte literal for 10^8, it shouldn't be noticeable. \$\endgroup\$maxb– maxb2018年11月27日 11:16:14 +00:00Commented Nov 27, 2018 at 11:16
-
\$\begingroup\$ This was the exact solution I had (I used
Z
instead ofJ
because I was lazy). \$\endgroup\$maxb– maxb2018年11月28日 07:41:46 +00:00Commented Nov 28, 2018 at 7:41
Perl 6, (削除) 18 (削除ここまで) 16 bytes
-2 bytes thanks to nwellnhof
{(0...*∉@_)-1}
Anonymous code block that counts up until it finds a number that is not an element of the input list, and returns the length of the range minus one
Prolog (SWI), (削除) 64 (削除ここまで) 35 bytes
-29 bytes thanks to @Jo King
L+X:-between(0,20,X),\+member(X,L).
JavaScript (ES6), 33 bytes
Thanks to @fhuvi for letting me know that my answer to this more recent challenge also works here.
a=>a.reduce(m=>m+a.includes(m),0)
Rust, (削除) 117, 113, 79, 78 (削除ここまで) 58 bytes
|l:&[u8]|(0..22).filter(|n|!l.contains(n)).next().unwrap()
GolfScript ((削除) 10 (削除ここまで) 9 bytes)
~.,),^0ドル=
Takes input from stdin in the format [5 4 1 5 4 8 2 1 5 4 0 7 7]
.
-
\$\begingroup\$ Shouldn't the
;
before the input string be counted in the program itself ? \$\endgroup\$Optimizer– Optimizer2014年09月29日 22:20:15 +00:00Commented Sep 29, 2014 at 22:20 -
1\$\begingroup\$ @Optimizer, that's simulating input from stdin because the online GolfScript site doesn't support a separate input field. \$\endgroup\$Peter Taylor– Peter Taylor2014年09月29日 22:52:14 +00:00Commented Sep 29, 2014 at 22:52
Xojo, 55 bytes
dim x as int8
while a.indexOf(x)>-1
x=x+1
wend
return x
Ruby, 22
x=->n{([*0..20]-n)[0]}
Explanation
- Input is taken as an argument to a lambda. It expects an
Array
ofInteger
s. - The input is subtracted from the array
[0,1,2..20]
. - Because the
Array
[0,1,2..20]
is sorted, the first element must be the mex.
-
\$\begingroup\$ Sweet, that was my first attempt, but I couldn't get the destructuring to work - I didn't think of surrounding it with brackets. Btw, you can use
20
instead of21
, because the input can only contain 20 elements. \$\endgroup\$Martin Ender– Martin Ender2014年09月29日 22:38:35 +00:00Commented Sep 29, 2014 at 22:38
Haskell, 30
f s=filter(`notElem`s)[0..]!!0
This works for lists of all size and lists beyond 20. This can be made 15 bytes long if Data.List is imported:
f s=[0..]\\s!!0
Scheme - 219
(define (A X) (define (B X) (if (equal? (length X) 1) (+ (car X) 1) (if (< (- (cadr X) (car X)) 2) (B (cdr X)) (+ (car X) 1)))) (if (empty? X) `() (if (equal? (car (sort X <)) 0) (B (sort X <)) (- (car (sort X <)) 1))))
Not very competitive. But I like writing scheme :),
Here's the ungolfed code:
(define (minExclude X)
(define (firstNonOneDifference X)
(if (equal? (length X) 1)
(+ (car X) 1)
(if (< (- (cadr X) (car X)) 2)
(firstNonOneDifference (cdr X))
(+ (car X) 1)
))
)
(let ([s (sort X <)])
(if (empty? X)
`()
(if (equal? (car s) 0)
(firstNonOneDifference s)
(- (car s) 1)
))
)
)
R, 27 bytes
Reads from stdin; computes the first element in the set difference between [0..20]
and x
.
x=scan()
setdiff(0:20,x)[1]
R, 36 bytes
which.min(y%in%x)
returns the index of the first element of y
that is not in x
.
x=scan()
y=0:20
y[which.min(y%in%x)]
Powershell, 28 bytes
for(;+$i-in$args){$i++}+$i
Test script:
$f = {
for(;+$i-in$args){$i++}+$i
#for(;$i++-in$args){}(--$i) # alternative version
}
@(
,(0 , 1)
,(1 , 0)
,(2 , 3, 1, 0, 1, 3, 3)
,(0 )
,(0 , 1, 2, 3)
,(3 , 5, 4, 1, 5, 4, 8, 2, 1, 5, 4, 0, 7, 7)
,(4 , 3, 2, 1, 0)
,(4 , 0, 0, 1, 1, 2, 2, 3)
,(10, 1, 0, 7, 6, 3, 11, 15, 1, 9, 2, 3, 1, 5, 2, 3, 4, 6, 8, 1, 18)
) | % {
$e, $a = $_
$r = &$f @a
"$($r-eq$e): $r"
}
Output:
True: 0
True: 1
True: 2
True: 0
True: 0
True: 3
True: 4
True: 4
True: 10
Explanation:
- Increment
$i
while the$args
array contains the integer value+$i
. - Output a last integer value
+$i
.
Desmos, 52 bytes
L=[0...20]
f(l)=L[[(i-join(e,l))^2.minfori=L]>0].min
05AB1E, (削除) 6 (削除ここまで) 5 bytes
2ÝIKн
-1 byte thanks to @emanresuA
Try it online or verify all test cases.
Explanation:
2Ý # Push a list in the range [0,26]
# (26 is the smallest 1-byte constant above 19)
IK # Remove all values of the input-list from this ranged list
н # Pop and push the first integer remaining (which is the minimum)
# (which is output implicitly as result)
-
1\$\begingroup\$ Would using a builtin number larger than 20 save bytes? \$\endgroup\$emanresu A– emanresu A2022年09月19日 09:06:58 +00:00Commented Sep 19, 2022 at 9:06
-
\$\begingroup\$ @emanresuA It indeed would, thanks. \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2022年09月19日 09:54:42 +00:00Commented Sep 19, 2022 at 9:54
0
to20
, the correct output is 21. I'll add a test case. Yes, the fixed range definitely makes it easier, though one could still arguably usesys.maxint
or2**64
if I didn't specify it. \$\endgroup\$