Python lowest missing integer: Codility Demo Task. What am I missing?

Question:

I’m playing with the Codality Demo Task. It’s asking to design a function which determines the lowest missing integer greater than zero in an array.

I wrote a function that works, but Codility tests it as 88% (80% correctness). I can’t think of instances where it would fail.

def solution(A):
#If there are negative values, set any negative values to zero
if any(n < 0 for n in A):
    A = [(i > 0) * i for i in A]
    count = 0
else: count = 1
#Get rid of repeating values
A = set(A) 
#At this point, we may have only had negative #'s or the same # repeated. 
#If negagive #'s, or repeated zero, then answer is 1
#If repeated 1's answer is 2
#If any other repeated #'s answer is 1
if (len(A) == 1):
    if (list(A)[0] == 1):
        return 2
    else:
        return 1
#Sort the array
A = sorted(A)
for j in range(len(A)):
    #Test to see if it's greater than zero or >= to count. If so, it exists and is not the lowest integer.
    #This fails if the first # is zero and the second number is NOT 1
    if (A[j] <= count or A[j] == 0): #If the number is lt or equal to the count or zero then continue the count
            count = count + 1
    elif (j == 1 and A[j] > 1): return 1
    else: 
         return count
return count

UPDATE:
I got this to 88% with the fixes above. It still fails with some input. I wish Codility would give the inputs that fail. Maybe it does with a full subscription. I’m just playing with the test.

UPDATE 2: Got this to 100% with Tranbi’s suggestion.

def solution(A):
#Get rid of all zero and negative #'s
A = [i for i in A if i > 0]
#At this point, if there were only zero, negative, or combination of both, the answer is 1
if (len(A) == 0): return 1
count = 1
#Get rid of repeating values
A = set(A) 
#At this point, we may have only had the same # repeated. 
#If repeated 1's answer is 2
#If any other repeated #'s only, then answer is 1
if (len(A) == 1):
    if (list(A)[0] == 1):
        return 2
    else:
        return 1
#Sort the array
A = sorted(A)
for j in range(len(A)):
    #Test to see if it's >= to count. If so, it exists and is not the lowest integer.
    if (A[j] <= count): #If the number is lt or equal to the count then continue the count
            count = count + 1
    else: 
         return count 
return count
Asked By: Astro.Bacon

||

Answers:

I don’t think this is true:

#At this point, we may have only had negative #'s or the same # repeated. If so, then the answer is 1+ the integer.
if (len(A) == 1):
    return list(A)[0]+1

If A = [2] you should return 1 not 3.

Your code is quite confusing though. I think you could replace

if any(n < 0 for n in A):
    A = [(i > 0) * i for i in A]

with

A = [i for i in A if i > 0]

What’s the point of keeping 0 values?

Answered By: Tranbi

Besides that bug for len=1, you also fail for example solution([0, 5]), which returns 2.

Anyway… Since you’re willing to create a set, why not just make this really simple?

def solution(A):
    A = set(A)
    count = 1
    while count in A:
        count += 1
    return count
Answered By: Kelly Bundy

I don’t think this is needed:

if (len(A) == 1):
if (list(A)[0] == 1):
return 2
else:
return 1

It’s already taken into account afterwards 🙂

Finally got a 100% score.

def solution(A):
    # 1 isn't there
    if 1 not in A:
        return 1
    # it's easier to sort
    A.sort()
    # positive "hole" in the array
    prev=A[0]
    for e in A[1:]:
        if e>prev+1>0:
            return prev+1 
        prev=e
    # no positive "hole"
    # 1 is in the middle
    return A[-1]+1
Answered By: Ilyes Hamdi
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.