'Is there a better solution in Python for this problem? Thanks

Given an array of scores sorted in increasing order, return true if the array contains 3 adjacent scores that differ from each other by at most 2, such as with {3, 4, 5} or {3, 5, 5}. Examples

scoresClump([3, 4, 5]) → true
scoresClump([3, 4, 6]) → false
scoresClump([1, 3, 5, 5]) → true

A solution below here seems to work but Translating it into Python looks tricky.

function scoresClump(scores) {
for (let i = 0; i < scores.length - 1; i++) {
if (scores[i + 2] - scores[i] <= 2) {
  return true;
}
}
return false;

}

I have tried this in Python and it keeps going out of range or giving the wrong output.

arr=[1,3, 5, 5]
i=0
while i<(len(arr)-1):
if (arr[i+2]-arr[i])<=2 and (arr[i+1]-arr[i])<=2:
 print("True")
 i=i+1  
else:  
 print("False")
 break


Solution 1:[1]

You're iterating until i < len(arr)-1, but you're reaching for arr[i+2], which is out of range.

In Python you usually do not need to use an index variable. As you've seen they're a source of errors, and Python offers cleaner syntax without using them. For instance:

# unpythonic
for i in range(len(scores)):
    print(scores[i])

# pythonic
for score in scores:
    print(score)

zip combines two (or more) things you can iterate over.
scores[2:] means "the scores list, but discarding the first two values".

scores = [1, 2, 3, 4, 5, 6]
for a, b in zip(scores, scores[2:]):
    print(a, b)
# 1 3
# 2 4
# 3 6
# zip then ends because it reached the end of scores[2:]

So, you can use zip and list slicing to compare the list with itself without index variables:

def scores_clump(scores):
    for a, b in zip(scores, scores[2:]):
        if b - a <= 2:
            return True
    return False


scores_clump([1, 3, 4, 5])
# 4 - 1 is not <= 2
# 5 - 3 is <= 2, return True

scores_clump([1, 3, 6, 7, 9])
# 6 - 1 is not <= 2
# 7 - 3 is not <= 2
# 9 - 6 is not <= 2
# reached end of loop with no match, return False

scores_clump([3, 3, 7, 7, 9])
# 7 - 3 is not <= 2
# 7 - 3 is not <= 2
# 9 - 7 is <= 2, return True

Taking a leaf from Max's answer, you can reduce it further using any:

def scores_clump(scores):
    return any(b - a <= 2 for a, b in zip(scores, scores[2:]))

Solution 2:[2]

Your if statement will reach arr[:-1] and then try and check two elements ahead of that, which don't exist, therefore going out of range. Rather than a while loop I would try something like this:

for x in range(0, len(arr)-2)

Solution 3:[3]

This is basically a "sliding window" problem where window size=3 and we keep iterating over the array until we find a window where difference between adjacent elements is less than or equal to 2.

Here we can simply check if difference between last and first element of the window is <=2 or not because we are given a sorted array.

def scoresClump(array):
  for i in range(2,len(array)):
    if array[i]-array[i-2]<=2:
      return True
  return False

print(scoresClump([1, 3, 5, 5]))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 neversnow1
Solution 3 Kshitij