ValueError: invalid literal for int() with base 10: '' *Codewars - python

I'm trying to solve an an exercise on Codewars:
Given an array of integers of any length, return an array that has 1
added to the value represented by the array.
the array can't be empty
only non-negative, single digit integers are allowed
Return nil (or your language's equivalent) for invalid inputs.
Examples
For example the array [2, 3, 9] equals 239, adding one would return
the array [2, 4, 0].
[4, 3, 2, 5] would return [4, 3, 2, 6]
test.assert_equals(up_array([2,3,9]), [2,4,0])
test.assert_equals(up_array([4,3,2,5]), [4,3,2,6])
test.assert_equals(up_array([1,-9]), None)
and I have written the code:
def up_array(arr):
print(arr)
strings = ''
for integer in arr:
if integer < 0 or integer >= 10:
return None
else:
strings += str(integer)
a_string = "".join(strings)
ints = int(a_string) + 1
to_string = str(ints)
return [int(x) for x in to_string]
It passed all of the tests, but it raises an error:
Traceback (most recent call last):
File "tests.py", line 15, in <module>
test.assert_equals(up_array([]), None);
File "/workspace/default/solution.py", line 11, in up_array
ints = int(a_string) + 1
ValueError: invalid literal for int() with base 10: ''
I don't understand why the code raises this error. Thanks

The exception you report makes sense only if arr is empty. That's an "invalid" input, but that doesn't mean it won't be given to you, only that you're not expected to give a normal response (you need to return None).
I suggest adding a check at the top of your function:
if not arr: # empty list
return None

Try this:
def up_array(arr):
num = 1 + int(''.join(str(ele) for ele in arr))
return [int(i) for i in str(num)]
print(up_array([2, 3, 9])) returns [2, 4, 0].
You can also add the if statement from Blckknght's answer at the beginning if you want.

Related

Python - len function not working as expected, and giving me the error "TypeError: object of type 'int' has no len()"

While studying linked lists from - https://composingprograms.com/pages/23-sequences.html#linked-lists
empty ='empty'
four = [1, [2, [3, [4, 'empty']]]]
x = [1,2];
def is_link(s):
"""s is a linked list if it is empty or a (first, rest) pair."""
return s == empty or (len(s) == 2 and is_link(s[1]))
print(is_link(four))
print(is_link(x))
The program recognizes four as a linked list, But when i plug in x it returns an error instead of returning "False".
If i change value of x to just [1] or [1,2,3] it returns as expected, but if i enter a normal list [1,2] with 2 values i run into this error. .Why is this?
Look at the executions, on your condition len(s) == 2 this only satisfies [1, 2] so it checks for the next one is_link(s[1]) which raises an error because it's a check length of integer in next iteration.
In [24]: print(is_link([1]))
[1]
False
In [25]: print(is_link([1, 2, 3]))
[1, 2, 3]
False
In [26]: print(is_link([1, 2]))
[1, 2]
2
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [26], in <module>
----> 1 print(is_link([1, 2]))
Input In [20], in is_link(s)
2 print(s)
3 """s is a linked list if it is empty or a (first, rest) pair."""
----> 4 return s == empty or (len(s) == 2 and is_link(s[1]))
Input In [20], in is_link(s)
2 print(s)
3 """s is a linked list if it is empty or a (first, rest) pair."""
----> 4 return s == empty or (len(s) == 2 and is_link(s[1]))
TypeError: object of type 'int' has no len()
The problem is in this part:
is_link(s[1])
When you pass x[1] to is_link method s is 2 (has type int) thus it doesnt have len() method. You need to check whether the argument in method is_link is list like that
return type(s) == list and (s == empty or (len(s) == 2 and is_link(s[1])))
When you try is_link([1,2]), then, since the list is of length 2, it will try to evaluate is_link(s[1]). Which in this case is is_link(2). Which then leads to len(2) which gives the error message, since 2 is not a list. len can only be applied on lists

Improving Python user defined max function

I am new to programming and am trying to understand how to "think" more programmatically in Python. I wrote a function that returns the largest element in an array without using max:
def max_userdefined(array):
"""
Finds largest value of nonempty array of numbers in O(n)
:param: list/tuple of values
:return: max value
"""
try:
assert isinstance(array, list or tuple)
result = array[0]
for element in array:
if element > result:
result = element
return result
except IndexError:
return 'Please pass in a nonempty array'
except AssertionError:
return 'Please pass in a list or tuple'
except TypeError:
return 'Please make sure elements of array are all floats or ints'
How can I improve the above code? Open to any criticism or if anyone can recommend a good Pythonic style guide.
def max_userdefined(array):
myMax = l[0]
for num in l:
if myMax < num:
myMax = num
return myMax
print max_userdefined ([1,2,3,4,5])
Output
5
Or You can do something like following by using sorted.
def max_userdefined(array):
return sorted(array)[-1]
>>> def umax(array):
global biggest
for num in array:
if num > biggest:
biggest = num
>>> biggest = int()
>>> nums = (1, 9, 6, 4, 5, 3, 2, 7, 0)
>>> umax(nums)
>>> biggest
9
For returning the greatest number from a list the simple algorithm followed is compare two numbers and keep the larger number in a variable, then print the variable OR you can use python shortcut using sort.
Using user defined function:
def greatest_ele_list(listobj):
greatest=listobj[0]
for i in range(len(listobj)):
if listobj[i]>greatest:
greatest=listobj[i]
else:
pass
return greatest
print greatest_ele_list([4,5,3,8,1])
Using sort:
def greatest_ele_list(listobj):
listobj2=listobj.sort()
return listobj2[-1]
print greatest_ele_list([4,5,3,8,1])
Output: >>> 8

Merge sort in Python - `int` object is not iterable

Here is merge sort implementation in Python. I am getting the error int object is not iterable when merge_arrays() function is called. Any suggestions will be highly appreciated.
arr = [1,5,4,7,6,8,3,2,9]
def merge_arrays(_arr_left, _arr_right):
sorted_arr = []
left, right = 0, 0
for i in range(0, len(arr)):
if (_arr_left[left] < _arr_right[right]):
sorted_arr.extend(_arr_left[left])
left += 1
else:
print _arr_right[right], right
sorted_arr.extend(_arr_right[right])
right += 1
return sorted_arr
def merge_sort(_arr):
if (len(_arr) <= 1):
return _arr
_arr_left = merge_sort(_arr[:len(_arr)/2])
_arr_right = merge_sort(_arr[(len(_arr)/2):])
return merge_arrays(_arr_left, _arr_right)
try:
merge = merge_sort(arr)
print merge
except Exception as e:
print e
That particular error is coming from the fact that you're saying sorted_array.extend(_arr_left[left]). You're asking for sorted_array to have appended to it every element of the "iterable" _arr_left[left]. But _arr_left[left] isn't really iterable, it's just whatever int is at index left in _arr_left.
If you don't try then except and print the Exception, you'll see a full stack trace that will tell you which line is bad.
File "merge.py", line 27, in <module>
merge = merge_sort(arr)
File "merge.py", line 22, in merge_sort
_arr_left = merge_sort(_arr[:len(_arr)/2])
File "merge.py", line 22, in merge_sort
_arr_left = merge_sort(_arr[:len(_arr)/2])
File "merge.py", line 25, in merge_sort
return merge_arrays(_arr_left, _arr_right)
File "merge.py", line 9, in merge_arrays
sorted_arr.extend(_arr_left[left])
TypeError: 'int' object is not iterable
So you can see the problem starts at line 9. You can also insert import pdb; pdb.set_trace() before you think the Exception comes up to run the python debugger and step through your program's progression to see where the Exception appears.
As other answers have mentioned, you need to change extent to append. However, as you said in comments, you are getting list index out of range error because you are iterating over the size of arr which is 9 but subarrays have much lesser length. Try changing your merging two arrays code to the following.
while (len(_arr_left) > left) or (len(_arr_right) > right):
if (len(_arr_left) > left) and (len(_arr_right) > right):
if (_arr_left[left] < _arr_right[right]):
sorted_arr.append(_arr_left[left])
left += 1
else:
sorted_arr.append(_arr_right[right])
right += 1
elif (len(_arr_left) > left):
sorted_arr.append(_arr_left[left])
left += 1
else:
sorted_arr.append(_arr_right[right])
right += 1
As you can see in the above code, we have to test for various conditions. If both subarrays contains elements, then we compare them to each other and append to sorted_arr depending on the value evaluation. If not then we append values from individual sub-arrays. It would have been easier if instead of using left and right, you were using pop so you wouldn;t have to keep tracking of left and right
Finally, here is the working version of your code. You also need to modify
return merge_sort(...) to sorted_arr = merge_sort(...) return sorted_arr so it doesn't print everytime it returns sorted_arr
In your line 9:
sorted_arr.extend(_arr_left[left])
sorted_arr is a list
_arr_left is a list
left is an int
So, the problem is:
>>> a = [1,2,3,4]
>>> a.extend(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>>
Solution:
You can use list.append() instead of extend().
>>> a = [1,2,3,4]
>>> a.append(5)
>>> a
[1, 2, 3, 4, 5]
>>>
PS: You might have other issues with your code.

How to add elements of a list in Python 3.5.5?

My assignment is:
Write a function sumOfPairs that has one parameter of type list. The
list can be empty or contain integers. The length of the list must be
0 or an even number. If the length of the list is not 0 and is not
even, the function should print an error message and return None. You
can assume the list contains only integers. The function returns the
list of the sum of each consecutive pair of the numbers in the list.
Example: If the list is [1,5,2,10,15,2,9,3], the function returns
[6,12,17,12].
My attempt so far is:
def sumOfPairs (list1: list):
if len(list1) != 0 and len(list1)%2 != 0:
print ("Error")
return (None)
else:
x = list1.index(int)
answer = []
while x<=len(list1):
newListValue=list1(x)+list1(x+1)
answer.insert(x,newListValue)
x=x+2
return (answer)
print (sumOfPairs ([1,5,2,10,15,2,9,3]))
Yet it yields the following error upon execution:
Traceback (most recent call last):
File "C:\Users\Andrew\Desktop\lab3.py", line 79, in <module>
print (sumOfPairs ([1,5,2,10,15,2,9,3]))
File "C:\Users\Andrew\Desktop\lab3.py", line 71, in sumOfPairs
x = list1.index(int)
ValueError: <class 'int'> is not in list
How can I fix this?
def sum_of_pairs(l):
if len(l) % 2: # if the length of the list mod 2 has a remainder, the list length is uneven
print("Error, uneven length list")
else: # else, step through the list in pairs and add each pairing
return [l[i]+ l[i+1] for i in range(0,len(l),2)]
In [3]: (sum_of_pairs([1,5,2,10,15,2,9,3]))
Out[3]: [6, 12, 17, 12]
A python function that does not specify a return value as in the if len(l) % 2: will return None by default so we do not need to explicitly return None.
In [11]: l = [1,5,2,10,15,2,9,3]
In [12]: [sum(pair) for pair in zip(l[0::2],l[1::2])]
Out[12]: [6, 12, 17, 12]
I don't particularly like your approach here, but let's take a look at the error specifically.
Traceback (most recent call last):
File "C:\Users\Andrew\Desktop\lab3.py", line 79, in <module>
print (sumOfPairs ([1,5,2,10,15,2,9,3]))
File "C:\Users\Andrew\Desktop\lab3.py", line 71, in sumOfPairs
x = list1.index(int)
ValueError: <class 'int'> is not in list
Now look at the line it occurs on, and try to say it in English
x equals the first index in list1 where the value is 'int'
Note that it's not the value is AN int! This is crucial, and is the reason for the error. Your list does not INCLUDE the class int. That would be something like:
[1,2,3,int,5,6,7,8] # not your list
Much easier would be to test that ALL your indices contain ints, then just iterate through the list. Let's try that (even though your exercise says otherwise, partially to keep you from just copy/pasting this!! :D)
def sum_of_pairs(lst: list):
if len(lst) == 0 or len(lst) % 2 != 0:
raise ValueError("Invalid list length")
# makes more sense to raise an exception here than print an error
if any(not isinstance(int, el) for el in lst):
# if any element is not an int:
raise ValueError("Invalid list contents")
result_list = []
for element in lst:
first_el = element
second_el = next(lst)
# advance the iterator once to grab the next element
result_list.append(first_el + second_el) # add them and append
return result_list
Or even easier if you know how to use the grouper recipe, which is in the pydocs for the itertools module here:
def grouper(iterable, n):
return zip(*iter([iterable])*n)
def sum_of_pairs(lst: list):
# validate here, I'm not going to re-write it
return [sum(pair) for pair in grouper(lst, 2)]

196 algorithm with optional inputs in function

what I am trying to do:
If the user specifies return_length=True when calling your function, it should return one plus the number of steps the algorithm required to reach a palindromic number. For example, with an input of 5280 and return_length=True, your function should return 4 (Note that this is the total number of entries in the sequence [5280, 6105, 11121, 23232]). With an input of 11, for example, the function should return 1 because it is already a palindromic number.
If the user did not specify return_length or specified return_length=False, your function should return the palindromic number at which the algorithm terminates. For example, with an input of 5280, the algorithm should return 23232 (an integer, not a string). Similarly, with an input of 89, it should return the integer 8813200023188.
Some background on the 196 algorithm:
Take any positive integer of two digits or more, reverse the digits, and add to the original number. This is the operation of the reverse-then-add sequence. Now repeat the procedure with the sum so obtained until a palindromic number is obtained. This procedure quickly produces palindromic numbers for most integers. For example, starting with the number 5280 produces the sequence 5280, 6105, 11121, 23232. The end results of applying the algorithm to 1, 2, 3, ... are 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 11, 33, 44, 55, 66, 77, 88, 99, 121, ... (Sloane's A033865). The value for 89 is especially large, being 8813200023188. (from http://mathworld.wolfram.com/196-Algorithm.html)
What I have so far:
def alg196(x, y = false):
if y==False:
while x == x[::-1]:
x==x+x[::-1]
return x
else:
seq = [x]
while x == x[::-1]:
x==x+x[::-1]
seq.append(x)
return seq
I get the error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "_sage_input_36.py", line 10, in <module>
exec compile(u"print _support_.syseval(python, u'alg196(34)', __SAGE_TMP_DIR__)" + '\n', '', 'single')
File "", line 1, in <module>
File "/sagenb/sage_install/sage-5.3-sage.math.washington.edu-x86_64-Linux/devel/sagenb-git/sagenb/misc/support.py", line 487, in syseval
return system.eval(cmd, sage_globals, locals = sage_globals)
File "/sagenb/sage_install/sage-5.3-sage.math.washington.edu-x86_64-Linux/local/lib/python2.7/site-packages/sage/misc/python.py", line 56, in eval
eval(z, globals)
File "", line 1, in <module>
File "", line 3, in alg196
TypeError: 'int' object has no attribute '__getitem__'
I am not sure how to fix this problem or the error exactly.
Taking some of the information for the answers i have this new code:
def alg196(x, y = false):
if y==False:
while str(x) == str(x)[::-1]:
x=str(x)+str(x)[::-1]
return x
else:
seq = [x]
while str(x) == str(x)[::-1]:
x = str(x)+str(x)[::-1]
seq.append(x)
return seq
But is still do not get the palindromic number for or the sequence to the palindromic number..
x[::-1] does not work on a number:
>>> 42[::-1]
TypeError: 'int' object has no attribute '__getitem__'
You need to convert it to a string, reverse it, then convert it back to an int:
>>> int(str(42)[::-1])
24
Secondly, the line
x==x+x[::-1]
does absolutely nothing. Don't confuse = and ==
something like this:
def algo(r,ret_len=None):
count=0
while 1:
r=str(r)
if r==r[::-1]:
break
else:
count+=1
r=int(r)+int(r[::-1])
return count+1 if ret_len else r
print (algo(5280,True))
print (algo(5280))
print (algo(89,True))
print (algo(89))
output:
4
23232
25
8813200023188
You can't get a 'slice' of an integer. You need to convert it to a string, first. x[::-1] <-- this operation is illegal if x is an integer.
Incidentally, this would be better written as a few functions-- functions that perform the calculations, and a function that runs functions while under a certain constraint, and takes in the return_length=True argument.
def reverse(n):
return int(str(n)[::-1])
def is_palindrome(n):
return str(n) == str(n)[::-1]
def alg196(n, return_length=False):
results = [n]
while not is_palindrome(results[-1]):
results.append(n + reverse(n))
n = results[-1]
return results[-1] if not return_length else len(results)
edit
A slightly quicker variation based on Ashwini Chaudhary's code. The above version produces a list of results, it's nice if you want to do something with the intermediate numbers. But, I think the following function is the best compromise between readability and speed. I have no idea why he starts with count=0 though.
def alg196(n, return_length=False):
count = 1
while not is_palindrome(n):
n = n + reverse(n)
count += 1
return count if return_length else n

Categories