0

please see comments, two different while loop conditions have different outcomes, is this because of and operator? I couldn't figure out why.

def longestPalindrome(s: str) -> str:
    output = ""
    
    for i in range(len(s)):
        temp = check(s,i,i)
        if len(output) < len(temp):
            output = temp
            
        temp = check(s,i,i+1)
        if len(output) < len(temp):
            output = temp
    return output

def check(s: str, l: int, r: int) -> str:
    while (l >= 0 and r < len(s) and s[l] == s[r]): 

  # while (s[l] == s[r] and l >= 0 and r < len(s)):
  # above will result in 'string index out of range' error which I couldnt figure out why

        l-=1;r+=1
    return s[l+1:r]
    

print(longestPalindrome("adaa")) # this will return "ada"
John Z
  • 79
  • 5
  • See also [this answer](https://stackoverflow.com/a/14892812/354577) – ChrisGPT was on strike Jan 17 '21 at 19:30
  • @Chris thanks for that but wouldn't it be the same for 'and' no matter what order I declare? That's why I'm confused why a different order of declaration matters in this case – John Z Jan 17 '21 at 19:35
  • 3
    Your while statement checks left to right. So when it goes to `s[l] == s[r]`, if any of the index value is out of range, it will error out. By checking for l and r first, you are exiting before it reaches the `s[l] == s[r]` condition – Joe Ferndz Jan 17 '21 at 19:35
  • No, that's the whole point of the dupe I suggested. Both `and` and `or` short-circuit. For example, `if False and foo == 0` never checks whether `foo` is equal to `0`. Compare `False and 0/0` (which returns `False`) and `0/0 and False` (which throws a `ZeroDivisionError`). – ChrisGPT was on strike Jan 17 '21 at 19:36
  • 1
    @JoeFerndz Thank you, now I understand why! It's about error handing isn't it, the whole function would break if there's an error calling out of index on the string, but if the condition is met it will safely exit the function. – John Z Jan 17 '21 at 19:39
  • Yes. You got it. The alternate is to check them before the while. This way it exits before it reaches that condition. See the posta Chris shared. It has more details – Joe Ferndz Jan 17 '21 at 19:41

2 Answers2

1

This is because the and operator is a short-circuit operator. This means that the second argument of the and operator is only evaluated if the first one is true.

In your case, at some point during the loop, r is equal to the length of s, so s[r] doesn't exist. The first while loop works because r < len(s) is false and thus short-circuits the last part of the condition. In the second loop, Python, tries to evaluate s[l] == s[r] first. As s[r] doesn't exist, an IndexError is raised.

You can check out the documentation here

Marc Dillar
  • 471
  • 2
  • 9
1

Your while statement checks left to right. So when it goes to s[l] == s[r], if any of the index value is out of range, it will error out. By checking for l and r first, you are exiting before it reaches the s[l] == s[r] condition

Joe Ferndz
  • 8,417
  • 2
  • 13
  • 33