Home > Mobile >  Is there a better solution in Python for this problem? Thanks
Is there a better solution in Python for this problem? Thanks

Time:02-05

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

CodePudding user response:

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:]))

CodePudding user response:

You can use this following function -

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

if you want a one-liner using any() -

def scoresClump(nums):
    return any(nums[x] - nums[x-2] <= 2 for x in range(2, len(nums)))
>>> scoresClump([3, 4, 5])
True
>>> scoresClump([3, 4, 6])
False
>>> scoresClump([3, 4, 5, 5])
True
>>> scoresClump([3, 4])
False
>>> scoresClump([3])
False
>>> scoresClump([3, 3, 7, 7, 9])
True

CodePudding user response:

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)

CodePudding user response:

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]))
  •  Tags:  
  • Related