This question already has answers here:
Python boolean evaluation order
(2 answers)
Does Python support short-circuiting?
(3 answers)
Closed 2 years ago.
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"
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
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
Related
This question already has answers here:
Is the shortcircuit behaviour of Python's any/all explicit? [duplicate]
(4 answers)
Closed 9 months ago.
Will python's all function exit as soon as it finds a False in the iterable? Or will it continue checking the rest?
For example, if i is not divisible by 20, will the below code continue checking if it is divisible by 19 and 18 and so on?
def min_divisible(target_n):
'''
Returns the smallest number that is divisible by all integers between 1 and n
'''
i = target_n
while not all((i%j == 0) for j in range(target_n,2,-1)):
i+=target_n
return f'{i:,}'
print(min_divisible(20))
all will stop the iteration as soon as it encounters a "falsey" object. You can see this with a simple example:
def produce_numbers():
for k in range(10):
yield k
print(k)
all(k < 3 for k in produce_numbers())
This prints
0
1
2
This is spelled out in Python's documentation. It states that the following is a functionally equivalent definition of all:
def all(iterable):
for element in iterable:
if not element:
return False
return True
This question already has answers here:
Python Bool and int comparison and indexing on list with boolean values
(4 answers)
Closed 1 year ago.
I was doing a leetcode problem and while reviewing a solution I was quite dumbfounded by a certain line in the solution. The leetcode problem in particular is https://leetcode.com/problems/binary-subarrays-with-sum/
The solution:
class Solution:
def numSubarraysWithSum(self, A: List[int], S: int) -> int:
res = 0
sm = 0
sums = collections.defaultdict(int)
for a in A:
sm += a
res += sums[sm - S] + (sm == S)
sums[sm] += 1
return res
I understand everything that is going on besides this line:
res += sums[sm - S] + (sm == S)
I have never seen a conditional in an addition operation before.
Conditional expressions evaluate to booleans, which in Python are just subtypes of int. False is 0, True is 1, so adding sm == S is the same as adding 1 if sm equals S or adding 0 otherwise.
This question already has answers here:
Why does my recursive function return None?
(4 answers)
Closed 2 years ago.
I would write a recursive function that take a list of number as argument and return maximum element of the list. I don't want to use max() function.
a = [2,1,3,5]
def f(a, m=0):
if m<a[0]:
m = a[0]
if len(a) == 1:
return m
else:
f(a[1:])
print(f(a))
but it returns None! how can I fix it?
You should define m in your else statement and add a return in it:
a = [2,1,3,5]
def f(a, m=0):
if m<a[0]:
m = a[0]
if len(a) == 1:
return m
else:
m = f(a[1:], m)
return m
print(f(a))
This question already has answers here:
How do "and" and "or" act with non-boolean values?
(8 answers)
Closed 4 months ago.
I came across following code while solving this problem:
f=lambda n:"a"[n:]or f(n-1)+chr(97+n)+f(n-1)
The function generates abacaba sequence of specific depth n
For example:
n = 2, output: 'abacaba'
n = 3, output: 'abacabadabacaba'
The question is, how does the code work? Namely, how does "or" operator work inside lambda? (I assume code above uses recursion, and to my knowledge, normally we use loops for recursion, but I don't see anything that resembles loops in the code above)
It works the same way it does anywhere else. If the left-hand argument of or is truthy, the expression evaluates to that; otherwise, it evaluates to the right-hand argument. In this case, "a"[n:] is the empty string when n > 0, so it's equivalent to
def f(n):
if n == 0:
return "a"
else:
return f(n-1) + chr(97+n) + f(n-1)
Let's break it down.
f = lambda # declare a variable f that is a function
n: # that takes an int parameter 'n'
"a"[n:] # if n is 0 return 'a'
or # else
f(n-1) # return a recursive call at n - 1
+ # plus
chr(97+n) # character from code 97 + n
+ # plus
f(n-1) # another recursive call
This question already has answers here:
List index out of range error on simple python for loop
(3 answers)
Accessing the index in 'for' loops
(26 answers)
Closed 4 years ago.
What is the difference between these 2 fragments of python codes?
I want to check whether an array contains the integers 1,2,3 in sequence as its elements?
def arrayCheck(nums):
for i in nums:
if(i <= (len(nums)-3)):
if (nums[i] == 1 and nums[i+1] == 2 and nums[i+2] == 3):
return(True)
return(False)
def arrayCheck(nums):
for i in range(0,len(nums)-2):
if (nums[i] == 1 and nums[i+1] == 2 and nums[i+2] == 3):
return(True)
return(False)
The first one gives wrong answer for the array:
arrayCheck([1,1,2,1,1,1,1,2,3])
but the second one is correct.
The first block i is elements of the parameter. The second, it's only their indices.
If you wanted the first to iterate over indices rather than the elements, use this
def arrayCheck(nums):
for i, _ in enumerate(nums):
if i <= len(nums)-3:
You can also use list slicing, by the way
if nums[i:i+2] == [1,2,3]:
return True