Just starting problem 164 for project euler, and i want a function to output a list of the sum of each set of 3 consecutive digits in a 20 digit number. Here is my function.
def func(n):
sumlist = []
m = str(n)
for i in range(0,18):
sumlist.append(sum(int(m[i])+int(m[i+1])+int(m[i+2])))
return sumlist
I keep getting the iteration over non sequence error and i can't figure out why i should. Any help would be appreciated, thanks.
EDIT
The full traceback is:
Traceback (most recent call last):
File "peproblem164.py", line 8, in ? print func(11201201201201201201)
File "peproblem164.py", line 5, in func
sumlist.append(sum(int(m[i])+int(m[i+1])+int(m[i+2])))
TypeError: iteration over non-sequence'
That's because
int(m[i]) + int(m[i+1]) + int(m[i+2])
isn't a sequence. It's an int. I believe you mean:
sumlist.append(sum((int(m[i]), int(m[i+1]), int(m[i+2]))
this will work because
(int(m[i]), int(m[i+1]), int(m[i+2]))
is a sequence.
All in all, it would be easier to work with a list of integers, rather than a string, so it would make sense to convert m into ints first:
m = map(int, str(n))
and then use Python's slicing syntax to get the subsequence sums:
for i in range(18): #Leaving out the start argument is equivalent to range(0, 18)
sumlist.append(sum(m[i:i+3]))
and it would be even more pythonic to use a list comprehension instead (not to mention faster):
sumlist = [m[i:i+3] for i in range(18)] #same thing as the for loop
You really don't need the sum call. Replace
sumlist.append(sum(int(m[i])+int(m[i+1])+int(m[i+2])))
with
sumlist.append(int(m[i])+int(m[i+1])+int(m[i+2]))
Related
i need to print a solution list for the input list using the below formula,
this is the code:
sub=[1,2,3,4,5,6,7]
a=[]
for i in sub:
def res(i):(sub/12)*100 #this is the formula
a.append(res(i))
print(a)
formula:
(sub/12)*100
i am getting this error:
Traceback (most recent call last):
File "c:\Users\suh\Desktop\se proj 2\backend.py", line 62, in <module>
a.append(res(i))
File "c:\Users\suh\Desktop\se proj 2\backend.py", line 61, in res
def res(i):(sub/12)*100
TypeError: unsupported operand type(s) for /: 'list' and 'int'
There are several things going on here:
First of all, don't define a function inside of a loop. You want to define the function that implements the logic of the formula separately and call it from within the loop.
You also need to use return in the function in order to send the calculated value back to whoever called the formula function.
Secondly, you want to go over each element in the sub list, apply the formula on it and then append the result to a list.
In addition, it is a good idea to provide meaningful variable names (a and res are not meaningful).
Applying the above, you get this:
def formula(num):
return (num / 12) * 100 # this is the formula
sub = [1,2,3,4,5,6,7]
sub_after_formula = []
for num in sub:
sub_after_formula.append(formula(num))
print(sub_after_formula)
Output:
[8.333333333333332, 16.666666666666664, 25.0, 33.33333333333333, 41.66666666666667, 50.0, 58.333333333333336]
As #JonSG mentioned, it is recommended to use the list comprehension instead of the for loop in cases like this:
sub_after_formula = [formula(x) for x in sub]
For this small list, the list comprehension / map approach is great.
For a larger list, or if you plan to do more mathematical operations on the list, it might be worth looking into the numpy library. This often results in a significant speed increase, and can simplify the code.
Once you convert the list to a numpy array, you can perform vectorised operations:
sub = [1,2,3,4,5,6,7]
sub_array = np.array(sub)
result = (sub_array/12) * 100
print(result)
Or we can use a function and pass the array directly:
def formula(num):
return (num / 12) * 100
sub_array = np.array(sub)
result = formula(sub_array)
print(result)
For a slight speed increase, you can use formula(np.fromiter(sub,dtype=np.int32)) from https://stackoverflow.com/a/59509701/9555388
sub=[1,2,3,4,5,6,7]
a=[]
for i in sub:
res = (i/12)*100 #this is the formula
a.append(res)
print(a)
You shouldn't make a function in a for loop. In this example as per me no function is needed.
You are getting the error actually because your formula is (sub/12)*100 while sub is a list. i is the item there not sub your formula should be (i/12)*100
You can't divide a list with 12., but an integer which is i here
i tried to use for loop to iterate through the length of input (string) but when i tried using len() OR range() they gave me error saying that the type is wrong.
this code is a start of Cows and Bulls game.
tried changing object type to list.
switched between sublime text and idle.
i checked the type of the input using the type() method
import random
target = [random.randint(0, 9) for i in range(4)]
turns = 0
all_cows = False
while not all_cows:
guess = input('Cows and Bulls!\nguess 4 numbers: ')
turns += 1
#tried doing range(guess) does not work! *type of guess is string
#len(guess) - error cant iterate through int
#range(guess) error cannot be interpreted as an integer
for item in len(guess):
if guess[item] == target[item]:
print('cow')
elif guess[item] in target:
print('bull')`
Program output:
Cows and Bulls!
guess 4 numbers: 1111
Traceback (most recent call last):
File "D:\Computers\Programming\Python\Codes\Exercises\17.py", line 8, in <module>
for item in len(guess):
TypeError: 'int' object is not iterable
Cows and Bulls!
guess 4 numbers: 1111
Traceback (most recent call last):
File "D:\Computers\Programming\Python\Codes\Exercises\17.py", line 8, in <module>
for item in range(guess):
TypeError: 'str' object cannot be interpreted as an integer
You need to combine range() and len(). By using
for index in range(len(guess)):
# your code here
you can iterate over the length of the guess.
You can also directly iterate over guess, but since you also need the index of each character, you need to use enumerate(). This will return two values for each character, the first is the index, the second is the character itself. So you would do:
for index, c in enumerate(guess):
# your code here with index as the index and c as the character
input() Function in python3 takes eac value as str
So you need to convert it into int by using int() Function
Check with following Code :
import random
target = [random.randint(0, 9) for i in range(4)]
turns = 0
all_cows = False
while not all_cows:
guess = input('Cows and Bulls!\nguess 4 numbers: ')
turns += 1
#Iterate String Directly
for item in guess:
#Convert Substring into int for using as Indices
if guess[int(item)] == target[int(item)]:
print('cow')
elif guess[int(item)] in target:
print('bull')
Thanks everyone for helping my out on that case.
seems like the problem is in me not understanding len() right, i forgot it returns the length as int and got confused when the err said object type int.
solution 1: using range(len(guess)) to iterate through through the length of the string.
solution 2: iterating through the string directly - wasn't what i searched for since i wanted to use the 'item' to index the string.
solution 3: using enumerate(guess) which i never heard of (so if someone is bored and want to explain it ill accept the explanation gratefully!
edit: got my answer.
Your problem is that your guess acquired by input is of type string (as are inputs). Then, the type of len(guess) is obviously int. You can't iterate over an int as it is not a sequence. You have a few options to overcome this problem:
iterate over the indices using range:
for i in range(len(guess)):
if int(guess[i]) == target[i]:
you could use enumerate:
for i, c in enumerate(guess):
if int(c) == target[i]:
Turn your input from the user to a list of ints:
guess = input('Cows and Bulls!\nguess 4 numbers: ')
guesses = [int(c) for c in guess]
for i in range(len(guess)):
if guess[i] == target[i]:
could also be done using map: guesses = list(map(int, guess))
I want to figure the length of the shortest word in a string
Here is my code:
def find_short(s):
for x in s.split():
return min (len(x))
The correct one:
def find_short(s):
return min(len(x) for x in s.split())
so what's the difference between my code and the correct one? which piece of code is not iterable?
min() takes a sequence, and returns the smallest item in that sequence.
len() takes a sequence, and returns a single length (the length of that sequence).
Your first code calls min() on each length... which doesn't make sense, because min() expects a sequence as input.
maybe wrong but my guess is that you are returning the minimum length of x for every x...
Input: what is your question
def find_short(s):
for x in s.split(): # here s.split() generates a list [what, is, your, question]
return min(len(x)) # you will pass the length of the first element because you're only passing length of one word len(what) to min and immediately trying to return.
you need to pass iterable items to min function not int type
Where as here
def find_short(s):
return min(len(x) for x in s.split())
#here there are three nested operations:
#1. split the string into list s.split() [what, is, your, question]
#2. loop the list and find the length of each word by len(x) and put it into a tuple compression (4, 2, 4, 8)
#3. pass that tuple compression to the min function min((4, 2, 4, 8))
# and lastly return the smallest element from tuple
def find_short(s):
for x in s.split():
return min (len(x))
Here, x contains individul words. For every iteration, you will get a new word in x. len(x) returns an int. Calling min on an int will give you the error:
'int' object is not iterable
The verbose solution should be like below:
def find_short(s):
min_length = s[0]
for x in s.split():
if len(x) < min_length:
min_length = len(x)
return min_length
Now, look at the correct version.
def find_short(s):
return min(len(x) for x in s.split())
Here, this len(x) for x in s.split() part would form a generator, where each element is int(length of individual words). And, min() is called on the generator, not on individual ints. So, this works perfectly fine.
In short
>> min(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>
>>min([1])
>> 1
I need to generate a string from random letters given in list take_from. The first time the function was executed it generated a phrase but all my following tries prompted an error "list index out of range". I can`t understand this error in my case and I tried while loop instead of for loop but it did not work either.
from random import randint
def make_a_phrase():
random_string = ''
take_from = ['a','b','c','d','e','f','g','h','i','j','k','l',
'm','n','o','p','q','r','s','t','v','u','w','x',
'y','z',' ']
for i in range(28):
random_string = random_string + take_from[randint
(0,len(take_from))]
return random_string
From the docs
random.randint(a, b)
Return a random integer N such that a <= N <= b.
Alias for randrange(a, b+1).
Therefore you can get values from 0 to len(take_from) - inclusive the endpoints - which in case of the upper bound would be out of list's index range as it is zero based and as such only has len(take_from) - 1 elements
In Python, lists are indexed with integers ranging from 0 to 1 less than the length of the list. E.g., a list with 10 items in it would have indexes from 0 to 9.
Your call to randint() attempts to get indexes from zero to the full length of the list, which will cause this exception. Change it to:
for i in range(28):
random_string = random_string + take_from[randint
(0,len(take_from)-1)]
The reason this happens, is because the len returns the length, but the last index is always the length - 1 (since indices start from 0).
So eventually, the random integer that comes up is the length, and of course, there is no element at that number.
Here is a simple example:
>>> i = [1,2,3]
>>> len(i)
3
>>> i[len(i)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
However, if you -1 from the length you will get the last item:
>>> i[len(i)-1]
3
You should change your loop to say:
for i in range(0, len(take_from)):
You are currently experiencing an off-by-one error because you only have 27 elements in your list, not 28.
You could try something like this instead
from string import ascii_lowercase
import random
def make_a_phrase():
return ''.join(random.choice(ascii_lowercase + ' ') for i in range(28))
I've just started programming, and I'm solving Project Euler problems with Python for practice.
(This is problem #2, finding the sum of the even fibonacci numbers within 4 million.)
My problem appears in the loop at the bottom, where I'm trying to locate the odd numbers in the list, and delete them.
del fiblist[i] gives me the following error message:
Traceback (most recent call last):
File ".../euler.py", line 35, in
del fiblist[i]
IndexError: list assignment index out of range
I don't see what I'm doing wrong here, and would really appreciate if anyone could help me see what I'm doing wrong here.
#euler2
def fibonacciList(limit):
'''generates a list of fib numbers up to N'''
mylist = []
a,b = 1,2
while True:
if a <= limit:
mylist.append(a)
a,b = b,a+b
else:
break
return mylist
fiblist = fibonacciList(4000000)
for i in fiblist:
if i%2 != 0: #if not even, delete from list
print i
del fiblist[i]
print fiblist
One problem here is that i is the item from the list, not it's index. So when you do del fiblist[i] you are not removing i, but the value that is at index i (which doesn't exist so you get an error). This can be fixed by using enumerate() to get indices to use, however, doing so introduces a new problem.
The main issue here is that you can't modify the length of a list while you iterate over it, as it messes with Python's iteration. One solution would be to copy the list and work on a copy, but the better one is to use a list comprehension to do what you want:
[i for i in fiblist if i%2 == 0]
This produces a new list with only the elements you want in. List comprehensions are a powerful tool, so I suggest you watch the video I linked for more.