0

here is my code:

def string_match(a, b):
  count = 0

  if len(a) < 2 or len(b) < 2:
    return 0

  for i in range(len(a)):
    if a[i:i+2] == b[i:i+2]:
      count = count + 1
  return count

And here are the results:

enter image description here

Correct me if I am wrong but, I see that it didn't work probably because the two string lengths are the same. If I were to change the for loop statement to:

for i in range(len(a)-1):

then it would work for all cases provided. But can someone explain to me why adding the -1 makes it work? Perhaps I'm comprehending how the for loop works in this case. And can someone tell me a more optimal way to write this because this is probably really bad code. Thank you!

IHaveAQuestion
  • 143
  • 2
  • 12
  • While I don't think this qualifies as a duplicate, you really should check out https://stackoverflow.com/questions/6822725/rolling-or-sliding-window-iterator. – Karl Knechtel May 15 '20 at 21:36

4 Answers4

1

But can someone explain to me why adding the -1 makes it work?

Observe:

test = 'food'
i = len(test) - 1
test[i:i+2] # produces 'd'

Using len(a) as your bound means that len(a) - 1 will be used as an i value, and therefore a slice is taken at the end of a that would extend past the end. In Python, such slices succeed, but produce fewer characters.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
1

String slicing can return strings that are shorter than requested. In your first failing example that checks "abc" against "abc", in the third iteration of the for loop, both a[i:i+2] and b[i:i+2] are equal to "c", and therefore count is incremented.

Using range(len(a)-1) ensures that your loop stops before it gets to a slice that would be just one letter long.

John Gordon
  • 29,573
  • 7
  • 33
  • 58
0

Since the strings may be of different lengths, you want to iterate only up to the end of the shortest one. In addition, you're accessing i+2, so you only want i to iterate up to the index before the last item (otherwise you might get a false positive at the end of the string by going off the end and getting a single-character string).

def string_match(a: str, b: str) -> int:
    return len([
        a[i:i+2]
        for i in range(min(len(a), len(b)) - 1)
        if a[i:i+2] == b[i:i+2]
    ])

(You could also do this counting with a sum, but this makes it easy to get the actual matches as well!)

Samwise
  • 68,105
  • 3
  • 30
  • 44
0

You can use this :

def string_match(a, b):
    if len(a) < 2 or len(b) < 0:
        return 0

    subs = [a[i:i+2] for i in range(len(a)-1)]
    occurence = list(map(lambda x: x in b, subs))

    return occurence.count(True)