Python- using sum in for loop with an error - python

Why should I write this program like this(first way) :
sum = 0
for i in range(1, 10):
if (i % 3 == 0) or (i % 5 == 0):
sum = sum + i
print(sum)
Why cant I write like this?(second way) :
for i in range(1, 10):
if (i % 3 == 0) or (i % 5 == 0):
print(sum(i))
In second way I receive this error :
TypeError: 'int' object is not iterable
What does this error mean exactly?
Where may I use sum function? Where not?
Must I make a list to use sum function?
Thanks a lot

As the doc says, the first argument to the builtin function sum() needs to be an iterable.
Lists and tuples are examples of iterables. An int is not an iterable.
Now, in your first approach, sum is a variable that you have introduced, and unfortunately it has the same name as the built-in function. This should, in general, be avoided (introducing user-defined names that conflict with names of standard functions or modules)
In your second approach, sum refers to the built-in function of that name, and it expects an iterable (eg, list or tuple) as its first argument, but your are passing i, which is an int object

When you wrote sum=0 you have overwritten the python function sum().
so when you write sum(1) you ask python to calculate 0(1) which is not possible since 0 is not iterable
In general, it is not advised to assign sum to a value
What could work is either of the following codes:
s=0
for i in range(1, 10):
if (i % 3 == 0) or (i % 5 == 0):
s+=1
print(s)
or better if you want to use the sum function:
print(sum([i for i in range(10) if (i % 3 == 0) or (i % 5 == 0)]))

Related

Adding every other integer from 0 to n (recursive func)

The function I am writing is meant to add every other integer from 0 to n. For example, if you inputted 6, you would get 12 because 6 + 4 + 2 + 0 = 12.
I was working with a list at first but realized I have to be working with integers instead. Below is my attempt, but I get TypeError: object of type 'int' has no len().
I'm confused as to how to fix this problem and make it a proper recursive function.
def addNum(n):
if len(n) == 0:
return 0
else:
return n[0] + addNum(n[::2])
print(addNum(6)) #example of how you would call the function
If you are looking to add just the alternating integers, it should be like
def addNum(n):
if n < 1 :
return 0
else:
return n + addNum(n-2)
print(addNum(6))
You pass an Integer to your function addnum, but you need a list. So you have to write addnum([6]) to create a list with the 6 as a single entry.
You have to call the function with the argument, reduced by 2 if you want to work without a list.
def addnum(n):
if n == 0:
return 0
else:
return n + addnum(n - 2)
print(addnum(6))
This gives the output 12.
so first of all the func len() is for lengths and you actually don't need that, what you need is a list comprehension. I assume that you don't know them so go and learn about them because they can help with these kinds of functions because they aren't that hard to write and are highly flexible.
The code below here does exactly what you want!
def addnum(n):
if n == 0:
return 0
else:
return sum([list for list in range(0,n+1,2)])
print(addnum(10))
first I create a function named addnum which has one parameter called n.
secondly I created the if else clauses, if the number is equal to 0 it returns 0. Else it returns the sum of every odd integer from 0 the the range. n+1 is here just to get the number you put in because the func range doesn't include the last value.

How can I use an element in a list as a parameter in range()?

So I have a for loop for i in range(0, arr[0]): and I want the stop parameter of the range() function to be variable based on the value of the first element in an array. When I do this, however, even though the value of arr[0] is an integer, python comes back and gives me an error saying TypeError: 'list' object cannot be interpreted as an integer. How can I either convert this element in the list to an integer or find another way to use its value as a parameter?
I am also using this same value to increment and decrement variables within this loop.
Thanks!
Full Code:
def diagonalDifference(arr):
stopInt = arr[0]
primary = 0
secondary = 0
pArrIndex = 1
sArrIndex = -1
for i in range(0, stopInt):
primary += arr[pArrIndex]
pArrIndex += arr[0]
for i in range(0, stopInt):
secondary += arr[sArrIndex]
sArrIndex -= arr[0]
return abs(primary - secondary)
This is for a challenge here
The purpose of the diagonalDifference function can be found in that link.
Try this:
def diagonalDifference(arr):
a=sum(v[i] for i,v in enumerate(arr))
b=sum(v[-i] for i,v in enumerate(arr,1))
return abs(a - b)
I did this because i read the Hacker-rank challenge

Why do I get a 'valueError' despite explicitly returning the expected number of values?

This is merge sort tweaked to count inversions. My code throws an odd error
(I'm implementing algos to learn python 3.x).
In line 11,
in merge_sort first_sorted_half, x = merge_sort(arr[:half])
[Previous line repeated 12 more times] ValueError: not enough values
to unpack (expected 2, got 1)
Even though I explicitly return two values? I'm new to python 3 so I'd like to understand exactly what's going on here, I can't seem to find a similar issue anywhere. A link to python docs for more on this would also be appreciated!
def merge_sort(arr):
if len(arr) <= 1:
return arr
half = int(len(arr)/2)
first_sorted_half, x = merge_sort(arr[:half])
second_sorted_half, y = merge_sort(arr[half:])
merged_halves, z = merge(first_sorted_half, second_sorted_half)
return merged_halves, x + y + z
def merge(first_half, second_half):
n = len(first_half) + len(second_half)
i = 0
j = 0
split_inversions = 0
ans = []
for k in range(n):
if i >= len(first_half):
ans.append(second_half[j])
j += 1
continue
if j >= len(second_half):
ans.append(first_half[i])
i += 1
continue
if first_half[i] > second_half[j]:
ans.append(second_half[j])
j += 1
split_inversions += len(first_half) - i
elif first_half[i] < second_half[j]:
ans.append(first_half[i])
i += 1
return ans, split_inversions
numbers = [3,2,1,4,5,6,8,10,9]
print(merge_sort(numbers))
The error you are getting says that your program executed that recursive call 12 times, and at the end it couldn't unpack the result.
What that means is, python expects you to return two values from merge_sort, because you unpack the result into first_sorted_half and x. However, when you return only arr from the condition len(arr) <=1, there is no value to unpack, only there exists the array.
So how you fix that is returning a value for the base case, like return arr, len(arr).
Whilst ilke444 is right - a bit more clarification is needed. To start: returning data variables is what you need but I do not know much about the len(arr) <=1 , and I am quite new to stackflow, I do not know this feature of Python 3. I specialize in Pygame/ standard packages.
First thing - arr in this "Code Snippet" (If it is) is not defined; and/or will need to be defined. Len stands for length as you know - and uses a quote (' ') to use it.
Like so:
len('arr')
would print:
3
because there are 3 Characters in this set. You are obviously new to python 3 as you said because the syntax is slightly different.
As this probably only solves the first bit - with this info I will leave you with 1 thing more.
Call to print requires a quote (' '),
Lists have [ ] Brackets instead of (),
Dictionaries have {} brackets and variables now require definition either by variable definition or function unless put in quote marks.
Thanks,
Jerry

Can I use a list while forming it in a list comprehension?

For example, the below code
primeList = []
for val in range(2, num):
if not any(val % i == 0 for i in primeList):
primeList.append(val)
How can I turn this exact piece of code into list comprehension?
No, you can't, because the list doesn't exist as a Python object until the comprehension is finished iterating. You can't reference an object that doesn't exist. Honestly, I would just leave this as a for loop - list comprehensions aren't a magic bullet to replace all list-constructing loops.
However... you can get tricky and use a generator, which is only evaluated on demand. Combining this with the extend() method of a list, which adds elements to the list as it obtains them (in my tests, anyway), you can use the current contents of the list you're extending as you extend it.
# make sure to set `num`
plist = []
plist.extend(c for c in range(2, num) if not any(c % p == 0 for p in plist))
Fair warning: as far as I know, the fact that extend() adds elements to the list as it produces them is not part of the specification, so whether this bit of code works could be implementation-dependent. But I tested it in Python 2.7 and 3.4 and got a list of primes each time.
Actually, if you really really want to, you can create an identical copy of the list within the list comprehension and refer to that...
primeListCopy = []
primeList = [primeListCopy.append(val) or val for val in range(2, num)
if not any(val % i == 0 for i in primeListCopy)]
This uses the fact that primeListCopy.append(val) or val evaluates to val, because assignment to list returns None and or evaluates to the right side value.
This is definitely worse performance-wise than a simple for-loop. I wrote this in response to OP's question "what could be the closest mimic when i had nothing but list comprehension. ( this is not a development code, just my experiments)"
That said, the additional work only adds O(n) of work so doesn't actually increase the algorithmic complexity of the loop. It's conceivable (though not very likely) that the list comprehension optimization will make this faster than the original for-loop.
#!/usr/bin/python
from __future__ import print_function
import math
def is_prime(x):
if (x == 0 or x == 1 or x < 0):
return False
for i in range(2, int(math.sqrt(x)) + 1):
if (not (x % i)):
return False
return True
def filter_primes(max):
return [val for val in range(2, max) if is_prime(val)]
def main():
primes = filter_primes(20)
print(primes)
if __name__ == "__main__":
main()
The code above starts with defining a function called is_prime(x) which returns True if x is a prime number, False otherwise. Then a function called filter_primes(max) uses is_prime with list comprehension to filter the prime numbers into an array that's returned. The maximum number of the range is specified via max. The main function just invokes the API to test it out.
EDIT:
But maybe I've misunderstood what you meant by "turn this exact piece of code into list comprehension". Depending on what you really want to do, using a generator is a great idea for dynamic purposes.

finding a remainder of an integer and a list element in python

I am trying to create a program that will create 10 random numbers and test if they are even or odd.
I have a list called rand_list created by
rand_list = []
for int in range(10):
rand_list.append(random.randint(1,1000))
intermediary = rand_list.append(random.randint(1,1000))
remainder2 = intermediary % 2 #this statement produces an error
print("the \i number is even \n", rand_list[int])
else:
print("the \i number is odd \n", rand_list[int])
I do not understand why if remainder == 0: does not work. it gives me {TypeError: unsupported operand type(s) for %: 'NoneType' and 'int'} Am i comparing two different types of objects?
remainder2 = intermediary %2 produces an error because list.append() returns None, as the error states. You're also appending 2 random ints to the list every time. What you probably want is intermediary = rand_list[-1] which will return the last element in the list.
In addition, please provide working/well-formatted code in your questions. The indentation is a little confusing and you're missing a line of code as well.
the append() function does not return anything. It modifies the list in place. What you would want to do is something like this
rand_list.append(random.randint(1,1000))
intermediary = rand_list[-1]
remander2= intermediary % 2
or perhaps cleaner:
intermediary = random.randint(1,1000)
rand_list.append(intermediary)
remainder2 = intermdiary % 2
What about as your if statement, you use
if number%2 == 0
# is even
else
# is odd
You are receiving the TyperError because you are assigning a method call to a veritable - this does nothing at all (hence the NoneType in your error message). You then try and perform an operation on this NoneType as if it were an Int. This wont work.
There are few mistakes in your code.
1) list.append() modyfies list in place, adding new element on the end.
It does not return anything, or to be more precise, it returns None.
So your intermediary == None and you cannot use % operator
with None...
You can assign your random number to variable:
x = random.randint(1,1000)
rand_list.append(x) # append it to your list
remainder = x % 2 # take remainder using
Because you only care if it is zero or not, you can later use fact,
that zero is equal to False in boolean context, and all other number
are treated as True
So you can write instead:
is_odd = x % 2
or more readable:
is_odd = bool(x % 2)
2) The other problem is, that you missed if in your code.
In fact, you didn't even use your remainder2 variable!
The correct code would be:
if (remainder2 == 0):
print("the \i number is even \n", rand_list[int])
else:
print("the \i number is odd \n", rand_list[int])
or using my advice above:
if is_odd:
print("the \i number is odd \n", x)
else:
print("the \i number is even \n", x)
3) The last thing is, that as #Padraic Cunningham pointed out,
you should not use int as variable name. It does not produce error,
as you shadow name of type int and builtin int().
To sum up, your code could look like this:
rand_list = []
for i in range(10):
x = random.randint(1,1000)
if (x % 2):
print(i, '-', x, "- the number is odd.")
else:
print(i, '-', x, "- the number is even.")

Categories