IndexError string index out of range - python

s="(8+(2+4))"
def checker(n):
if len(n) == 0:
return True
if n[0].isdigit==True:
if n[1].isdigit==True:
return False
else:
checker(n[1:])
else:
checker(n[1:])
This is what I have so far. Simple code, trying to see if a string meets the following conditions.
However when i perform checker(s) i get:
True
IndexError: string index out of range
Any help? Thanks in advance
Edit: The function's purpose is to produce true if the string contains only single digit numbers, and false if 2 or more-figured digits exist in the string.

When the length of n is 0, the n[0] part is going to raise an error because the string in empty. You should add a return statement there instead of print.
def checker(n):
if len(n) < 2:
return True
if n[0] in x:
Note that the conditions must be len(n) < 2 otherwise you'll get an error on n[1] when the length of string is 1.
Secondly you're trying to match characters to a list which contains integers, so the in checks are always going to be False. Either convert the list items to string or better use str.isdigit.
>>> '1'.isdigit()
True
>>> ')'.isdigit()
False
>>> '12'.isdigit()
True
Update:
You can use regex and all for this:
>>> import re
def check(strs):
nums = re.findall(r'\d+',strs)
return all(len(c) == 1 for c in nums)
...
>>> s="(8+(2+4))"
>>> check(s)
True
>>> check("(8+(2+42))")
False
Working version of your code:
s="(8+(2+4))"
def checker(n):
if not n: #better than len(n) == 0, empty string returns False in python
return True
if n[0].isdigit(): #str.digit is a method and it already returns a boolean value
if n[1].isdigit():
return False
else:
return checker(n[1:]) # use return statement for recursive calls
# otherwise the recursive calls may return None
else:
return checker(n[1:])
print checker("(8+(2+4))")
print checker("(8+(2+42))")
output:
True
False

You should do return True after the first if statement, not print True. The function continues to run after that statement and hits an error when the input is size 0.

I can't reproduce your error.
I had to fix a few things:
Indentation, which I'm guessing was just a problem pasting into the page
.isdigit() is a function; calling .isdigit==True is going to compare a function object with True, which is never going to be true. I changed .isdigit==True to .isdigit()
I made sure return value gets bubbled up - without this, the recursion completes okay but the outermost function just returns "None".
Aside from that, a few print statements show that this is working as expected
s="(8+(2+4))"
t="(8+(20+4))"
def checker(n):
print "checking %s" % n
if len(n) == 0:
print "Returning true"
return True
if n[0].isdigit():
if n[1].isdigit():
print "returning false"
return False
else:
return checker(n[1:])
else:
return checker(n[1:])
print checker(s)
print checker(t)
Output:
checking (8+(2+4))
checking 8+(2+4))
checking +(2+4))
checking (2+4))
checking 2+4))
checking +4))
checking 4))
checking ))
checking )
checking
Returning true
True
checking (8+(20+4))
checking 8+(20+4))
checking +(20+4))
checking (20+4))
checking 20+4))
returning false
False

Related

Why does this function return "None" if the number isn't even? How can I make it return "False" without using an else condition?

def my_function(n):
if(n % 2 == 0):
return True
print(my_function(2))
print(my_function(5))
Output:
True
None
I understand that 'False' has to be explicitly specified to be returned by the function but don't exactly understand why.Can this function be made to return false without an else loop incorporated?
def my_function(n):
if(n % 2 == 0):
return True
return False
Since it is only one return indication, otherwise it returns none, 'nothing'. Here we have forced it to return False otherwise.
1st question: If you did not specify any return in a Python function, it will return none.
2nd question: You can do return n%2 == 0, which will return true if n is even number and false if n is odd number.
To answer your question: you are trying to get a False value out of something that doesn't have a value at all. Therefore it is 'none'. Just because it isn't true doesn't necessarily mean it's false.
There are two common ways to go about doing this though:
def my_function(n):
return n % 2 == 0
This will evaluate to either True or False depending on the parameter n and then it will return the value.
The other way:
def my_function(n):
if(n % 2 == 0):
return True
return False
Here, if we pass the if check, the function will return True and it will never make it to the return False statement. Vice versa, if we don't pass the if check we will instead return False. I prefer to write code this way because it's a little more specific in what the code is doing. Either way works though

I want to write a function in python which returns true if all the digits are even

The function is all_even in which you input an int and it returns bool. It returns true if all the digits are even. e.g. all_even(2224) gives true and all_even(1362) gives false.
I wrote the code but it is not working properly.
This is what I have:
def is_very_even(num: int) -> bool:
even = False
strnum = str(num)
for ch in strnum:
if int(ch)% 2==0:
even = True
return even
The code gives true even if the num has a single even num and the rest are odd e.g all_even(231) is true which is supposed to be false. Can somebody tell me what is wrong with it.
You could use a recursive approach (without converting to a string):
def allEven(N): return True if N==0 else N%2==0 and allEven(N//10)
output:
allEven(246) # True
allEven(123) # False
Note that the issue with your function is that you set even to True as soon as you encounter an even digit. If there is an odd digit after that, your even variable remains True. This will tell you that "at least one" digit is even, not that they are all even.
You are checking if all the numbers are even. So first assume that it's true, all the numbers are even and set even = True. Then check if there is any odd number in the string. If there is, then set even = False
Now, if there is any odd number in the string, even will be False and therefore we can verify it.
def is_very_even(num: int) -> bool:
even = True
strnum = str(num)
for ch in strnum:
if int(ch)% 2 !=0:
even = False
return even
This code can also be improvised like this. We don't need to keep checking if we found a single odd number. We can just return false immediately. And if all the numbers checks out but none returns false, then it must be an all even string.
def is_very_even(num: int) -> bool:
for ch in str(num):
if int(ch)% 2 !=0:
return False
return True
I would solve it like this:
def is_very_even(s) -> bool:
return all(int(x) % 2 == 0 for x in str(s))
This converts every character to an integer and checks if it is even with modulo. This is processed in a so called generator expression.
Then we use the builtin all method to check if the generator delivers only True values.

How to find if there are 2 elements of same value consecutively in a list?

For example,
[1,3,3,5] should return True while [1,3,1,3] should return False.
I am looking for a simple solution using loops.
I tried the following:
def conseq(nums):
for i in range (len(nums)):
if nums[i]==nums[i+1]:
return True
break
else:
return False
The first time your function encounters 2 consecutive numbers which are different, it returns False. Returning from a function ends that function immediately, the function does not continue after that. This is also why the break is not necessary.
Another issue with your code is that once you reach the final number, nums[i + 1] will access out of the bounds of the array. That's why you should iterate over len(nums) - 1 rather than len(nums) - there's no reason to check the final number because there's nothing after it.
def conseq(nums):
for i in range(len(nums) - 1):
if nums[i]==nums[i+1]:
return True
# Only return False once we've exhausted all numbers.
# Since we didn't return True so far - it means there are
# no consecutive equal numbers, so we can safely return False
return False
the return ends the function, so here it will stop the processing as well
your true statement mostly works, and the break is unnecessary
you don't want the else statement until after the for loop ends (it returns False only if everything else has been parsed)
Also the way you parse through the code, nums can't access nums[i+1] when you're at the final nums so you need the range len(nums) - 1
If you feel like putting an else that does nothing, you can with a single semicolon or pass I believe, but the else is unnecessary here
def conseq(nums):
for i in range (len(nums)-1):
if nums[i]==nums[i+1]:
return True
else:
;
return False
You can't return False until the loop is done (since the match may be in the part of the list you haven't checked yet). And the break after return will never happen (since return ends the function and everything in it).
Enumerate list without last (to avoid try catch for i+1 being out of range) then compare each item with next one and return True if they are same. After loop return False because none are similar consequtively (returns break functions)
def function(number_list):
for i, item in enumerate(number_list[:-1]):
if item == number_list[i+1]:
return True
return False
def conseq(nums):
for i in range (len(nums)):
if nums[i]==nums[i-1]:
return True
return False
I modified your Code. Please check and let know if useful
def conseq(nums):
flag=True
for i in range (len(nums)-1):
if nums[i]==nums[i+1]:
print(True)
flag=False
break
else:
continue
if(flag):
print(False)
nums=[1,3,3,5]
nums1=[1,3,1,3]
conseq(nums)
conseq(nums1)
We have many solutions here already. I have tried out using numpy without a loop:
>>> import numpy as np
>>> f = np.array([1,3,3,5])
>>> (np.where(np.diff(f) == 0)[0]).astype('bool')[0] #check if we have any difference of two elements 0?
True

if...else.. compare character list and string by python

I am writing an for loop comparing the character in list and string, then return False if the character is not same. But I keep receiving True. Can someone explain what is wrong with my code?
def compare (sofar, orig):
if len(sofar) == len(orig):
for i in range(len(orig)+1):
if orig[i] == sofar[i]:
return True
else:
return False
return False
here is the result i got:
In [29]: compare (['a','v','c','c','s'], 'abccs')
Out[29]: True
But it suppose to be False
You could just join the characters back into a string
def compare (sofar, orig):
return ''.join(sofar) == orig
Otherwise, if you wanted a loop, you need to compare all characters before you return True. You can return False when the first does not match
Here's another one liner using all() over a loop of zipped characters.
You will need the length check before this statement
return all(x == y for x, y in zip(sofar, orig))
Or going back to the original code, invert your logic
def compare (sofar, orig):
if len(sofar) != len(orig):
return False
for i in range(len(orig)):
if orig[i] != sofar[i]:
return False
return True
If your function reaches a return statement, that's it. Your function has returned a value and it will not continue running.
You can use a generator to implement your logic. The below solution allows you to iterate lazily; retrieve a Boolean list with a letterwise comparison via list; or check if all letters align via all.
def compare(sofar, orig):
if len(sofar) == len(orig):
for i in range(len(orig)):
if orig[i] == sofar[i]:
yield True
else:
yield False
res = list(compare(['a','v','c','c','s'], 'abccs'))
# [True, False, True, True, True]
res = all(compare(['a','v','c','c','s'], 'abccs'))
# False
Another way of writing your logic without explicit iteration:
lst = ['a','v','c','c','s']
mystr = 'abccs'
res = ''.join(lst) == mystr
The statement return is exit from your function.
So your prog only compares the first element.
if orig[i] != sofar[i]:
return False
would do it

Int conditional always returning true? Python

I have a function called check defined like so
def check(n):
if n > 17325551999:
return True
return False
which is always returning true. eg
>check(1000000000)
True
>check(5)
True
Can anyone give me some insight as to why this is happening? Is it because the number is larger than the largest possible int?
edit: I've added a picture of my python prompt.
Updated answer:
From your screenshot it is clear you didn't post the same code here as what you are actually running:
def check(num):
if n > 17325551999:
return True
return False
either raises a NameError for 'n' or tests n as a global if it is defined. The actual parameter to the function is called num, and is completely ignored in the function.
In other words, you'd have to assign to the n global to make your version work.
The fix is to test the right parameter:
def check(num):
return num > 17325551999
Previous answer before the screenshot was posted:
You are not passing in integers. With integers your code works just fine:
>>> def check(n):
... if n > 17325551999:
... return True
... return False
...
>>> check(5)
False
Instead you are probably passing in strings instead:
>>> check('5')
True
In Python 2, numbers always sort before strings (a mistake remedied in Python 3), so any number is always going to be 'smaller' than a string:
>>> '0' > 0
True
Avoid this problem by making sure your function is called with an integer argument, or explicitly convert n in the function:
def check(n):
return int(n) > 17325551999:
Note that the > operator already returns True or False, no need to use if here.

Categories

Resources