-2

Details:

  • There are two strings x and y.

  • Count the number of occurrence of y in x as follows:

    • Length of y is 3.

    • Increment the "count" value when y == x[i] x[i+2] x[i+4]


Example:

x = "aabbcc"
y = "abc" 
output: 2

My Code:

def solution(x, y):
    i, count = 0, 0
    j = i + 2
    k = i + 4
    
    while i+4 < len(x):
        cur = x[i]
        while i < len(x) and i != j:
            i += 1
        while i < len(x) and i != k:
            i += 1
        count += 1
        
    return count
    
solution(x, y)
            

I am getting count = 1. It should give count = 2


meallhour
  • 13,921
  • 21
  • 60
  • 117
  • trying adding a `print(i)` statement above the line that's giving you the error, then try to establish how these values of `i` are being generated – bn_ln Sep 26 '22 at 00:02
  • 1
    I'm not sure why your question was downvoted, it appears to meet basic criteria. However, the problem is fairly easy to spot. Your error message will have included a line number (it's a good idea to share the entire stack trace in the question). And the line it fails on is the second `res.append(x[i])` - this happens because you increase `i` under certain conditions, but don't check that it no longer fits within the string. (also, it appears that in the problem description, it should read `y == x[i] x[i+2] x[i+4]` for any `i`) – Grismar Sep 26 '22 at 00:03
  • @Grismar I have modified my question. can you please take a look now? – meallhour Sep 26 '22 at 00:17
  • @Grismar I downvoted the question because it does not show an attempt to analyze the problem or to understand why/where the code goes wrong; and because a straightforward solution is available by combining two elementary techniques that are covered in very popular canonical duplicates. I don't want to close the question as a duplicate because it *can* be approached other ways; but right now, it isn't even clear whether to approach this as a technique question or a debugging question. I voted to close as "needs more focus" on these grounds. – Karl Knechtel Sep 26 '22 at 00:37

3 Answers3

1

There's a couple of logic errors in your code.

The problem happens here:

        while i < len(x) and i != j:
            i += 1
        res.append(x[i])

You keep increasing i until it is either len(x) or greater, or until it is the same as j. But since you set j to be 2 at the start (and never update it), it will simply end up setting i to len(x). And x[i] will thus fail, since x[len(x)] tries to index an element just outside x.

However, there's a few more remarks to make:

  • you collect what you find in res, but really only want a number (e.g. 2) as a result
  • you define count but don't use it
  • you track the coordinates in the string in three separate variables (i, j, k) and have a lot of logic to increment the first, but really all you need is to step through the string one position at a time, and look at the offsets directly

Given all that and the problem description, you were probably going for something like this:

x = "aabbcc"
y = "abc"


def solution(x, y):
    i, count = 0, 0

    while i + 4 < len(x):
        if (x[i], x[i+2], x[i+4]) == (y[0], y[1], y[2]):
            count += 1
        i += 1

    return count


print(solution(x, y))

However, Python has some cleverness that would make it even simpler (or at least shorter):

def solution(x, y):
    count = 0

    for i in range(len(x)-4):
        if x[i:i+5:2] == y:  # slicing with a stride of two, instead of direct indexing
            count += 1

    return count

Or even:

def solution(x, y):
    return len([x for i in range(len(x)-4) if x[i:i+5:2] == y])

But that's favouring brevity over readability a bit too much, I feel.

Grismar
  • 27,561
  • 4
  • 31
  • 54
  • The last one building a list repeating is weird. Mine was `sum(x[i:i+5:2] == y for i in range(len(x)))` (yes I'm too lazy to think about how much to subtract exactly). – Kelly Bundy Sep 26 '22 at 00:26
  • @KellyBundy user Nick contributed that solution already - I went for this, since it takes OP's idea of collecting the results in a list and then somehow getting to the answer from that. I wouldn't write it like that for any real situation though. Nick's solution (and yours, adding the `- 4`) is clever, if brevity is key. – Grismar Sep 26 '22 at 00:28
  • Ah yes, hadn't scrolled down yet. Ok, I see that and raise you a `[*zip(x,x[2:],x[4:])].count((*y,))`. – Kelly Bundy Sep 26 '22 at 00:29
  • @KellyBundy that one doesn't even need a code obfuscator! :) – Nick Sep 26 '22 at 00:30
1

A generator expression solution, taking advantage of True/False == 1/0 in a numeric context:

def solution(x, y):
    return sum(y == x[i:i+5:2] for i in range(len(x)-4))
Nick
  • 138,499
  • 22
  • 57
  • 95
0

Increment the "count" value when y == x[i] x[i+2] x[i+4]

This is the same as simply creating the string consisting of x[0], x[2], x[4]... (every even-numbered character) and the string consisting of x[1], x[3], x[5]... (every odd-numbered character); counting the occurrences of y in each; and adding those two results together.

Creating the strings is trivial, and a common duplicate. Counting occurrences of a substring is also well-trodden ground. Putting these tools together:

def spread_substrings(needle, haystack):
    even_haystack = haystack[::2]
    odd_haystack = haystack[1::2]
    return even_haystack.count(needle) + odd_haystack.count(needle)
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
  • Yes. There is nothing in OP's specification to suggest that the answer shouldn't be `2`. The problem OP reports is due to the interlacing, not due to overlooking an overlapping match. If OP **wants** overlapping matches, *there are other answers at the linked duplicate explaining how to deal with that*. Frankly, I am starting to get the impression you have a personal vendetta against me, and I don't appreciate your pattern of nit-picking my answers and/or comments with pithy or sarcastic remarks. – Karl Knechtel Sep 26 '22 at 00:44
  • I'd say their specification *"Increment the "count" value when y == x[i] x[i+2] x[i+4]"* rather clearly allows overlapping. No "personal vendetta", I don't even remember interacting with you before. – Kelly Bundy Sep 26 '22 at 00:49
  • That is interlacing, not overlapping. Overlapping is detecting a match on `x[i+2] x[i+4] x[i+6]` *in addition to* that one. Interlacing is detecting a match on `x[i+1] x[i+3] x[i+5]` in addition - which my code does, because it works by explicitly deinterlacing first. – Karl Knechtel Sep 26 '22 at 00:50
  • No, the one you're missing is for i=2, because it *overlaps* the one for i=0. – Kelly Bundy Sep 26 '22 at 00:53
  • That's... what I said. – Karl Knechtel Sep 26 '22 at 01:02
  • Wasn't in your comment initially. Now your comment says it's not overlapping and then right away explains that it's overlapping. I think you misunderstood my point, I didn't mean the step=2 part of their specification, I meant the incrementing the count for every i where a certain condition holds. Phrased as that is, I really think there's no reason to not count the match for i=2. It suggests doing what the other answers did (loop over the possible i-values and check/count). – Kelly Bundy Sep 26 '22 at 01:14