'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 |
