I'm getting an unexpected result from a program designed to make a list of even Fibonacci numbers. The part of the code that finds all the numbers works fine, but when it gets to the
if i % 2 != 0
fib_list.remove(i)
part something seems to go wrong, because it doesn't take out all the odd numbers. Below is the entire program. What am I doing wrong?
fib_list = [1, 2, 3]
for i in range(4, 4000001):
if (i - fib_list[-1] - fib_list[-2]) == 0:
fib_list.append(i)
print fib_list
for i in fib_list:
if i % 2 != 0:
fib_list.remove(i)
print fib_list
You are iterating over a list while modifying it. Don't do that.
[x for x in fib_list if x % 2 == 0]
Related
I am trying to build a function that will take a number and return a list. If the number is even, the second integer of the list will be the number divided by two. If it is odd, then following number will be number multiplied by 3 plus one and so on until it reaches 1.
For example:
Function(5) will give
[5, 16, 8, 4, 2, 1]
My code is:
def Collatz(n):
out=[]
while n>1:
if n%2==0:
out.append(n/2)
elif n%2!=0:
out.append((n*3)+1)
print(out)
Collatz(20)
It doesn't produce anything. Any suggestion? I want to do this with while loop.
This code is close to be working, a few insights and improvements:
Change n inside the while loop (otherwise n remains larger than 1 and you get infinity loop)
Use lower case in function names and use underscore to separate between words
def collatz(n):
out = [n]
while n > 1:
if n % 2 == 0:
n = int(n / 2)
elif n % 2 != 0:
n = (n * 3) + 1
out.append(n)
print(out)
# [5, 16, 8, 4, 2, 1]
collatz(5)
It is because the while loop never terminates, this is because you aren't actually changing the value of n each time. So before you append to the array say something like n=n/2 (or whatever the calculation is) then append n. This means that n will eventually reach one and you get a print out
The problem with your code is you are not decrementing the value of n which is leading to an infinite loop.
Every time when you are appending a new value in the list you also need to update the value for n.
Try this:
def Collatz(n):
out=[]
while n>1:
if n%2==0:
out.append(n//2)
#updating n
n= n//2
elif n%2!=0:
out.append((n*3)+1)
#updating n
n= (n*3)+1
print(out)
Collatz(20)
Output:
[10, 5, 16, 8, 4, 2, 1]
Try this:
def Collatz(n):
l=[n]
while l[-1]!=1:
x=l[-1]/2 if l[-1]%2==0 else l[-1]*3+1
l.append(int(x))
return l
Here's a version that works.
def Collatz(n):
out=[n]
while n>1:
if n%2==0:
n = n/2
else:
n = (n*3)+1
out.append(int(n))
return out
print(Collatz(5))
Some notes on your version:
Your loop never updates "n" so n stays at its initial value forever, leaving you in an infinite loop.
The "elif" can be simply "else" - if the value is not even, then it's odd (assuming we're working with integers)
If you want the initial value to be in the list, we should probably initialize the list that way.
In your problem statement, you say you need the function to "return a list". Printing from inside the function is fine if that's really all you need, but if we actually return the list with a return statement, then the list it generates can be used by other code.
If you're using Python 3, the operation n/2 will return a float, even if n was an integer to start. If we only want integers in our list, we need to do one of two things:
Make it explicitly integer division with n//2
Or re-cast n to an integer with int(n) before we insert it into the list. (Which is how I did it here.)
Notice that your code doesn't change n.Therefore your loop never terminates. Check this out:
def collatz(n):
my_list = [n]
while n > 1:
if n % 2:
n = n * 3 + 1
else:
n = n / 2
my_list.append(n)
return(my_list)
I am making a program where I can fix the sequence of a list, the sequence is to be followed with a difference of 2. In this program if the difference is less than 2 I need to replace/change a certain number. Well, I have done most of the part but the problem is I can't replace it properly, and since I can't change the number in the process my output also comes out wrong.
list_1 = [1,2,5]
for i in range(1, len(list_1)):
htl = list_1[i]-list_1[i-1]
if not htl == 2:
list_1[i-1] += 2
print(list_1[i-1])
The output is:
3
4
But it's wrong, the correct ouput is:
3
Because I only need to change the number 2 to 3 to make it a correct sequence.
What I am doing in my code is that, I am subtracting backwards to spot the differences. If there is a difference, I am trying to add 2 to number it is being subtracted from, and then change the number that is being subtracted. But in my program I am having problem in replacing. For example(the subtraction starts from index 1 - index 0, index 2 - index 1 and it goes on): 2-1 = 1 so it's not clearly following the sequence, and I am trying to replace the 2 in 'list_1' with 3(by adding 2 to the number that index 1 is being subtracted from). I can't replace the number and since I can't replace that,the next output comes that shouldn't be there because only one change is needed.
My way may be really tangled up, but it was the best I could think of, if there is a faster way I would really appreciate the help. But otherwise I did like to fix my Code, where the general idea is to follow the sequence of 2.
The attribution is wrong:
list_1 = [1,2,5]
for i in range(1, len(list_1)):
htl = list_1[i]-list_1[i-1]
if htl != 2:
list_1[i] = list_1[i-1] + 2
print (list_1)
Output:
[1, 3, 5]
But in the end, what you want is simply a sequence starting at an initial point and with a step of 2 and with a certain number of points
start = 1
points = 3
stop = points * 2 + start
list_1 = list(range(start, stop, 2))
Output:
Out[11]: [1, 3, 5]
Less than 2?
I also think you were changing the -1 list value rather than the current index.
This should work?
list_1 = [1,2,5,6,7,8,15]
for i in range(1, len(list_1)):
htl = list_1[i]-list_1[i-1]
if htl < 2:
list_1[i] =list_1[i-1]+2
print(list_1[i-1])
print(list_1)
If i understand your explanation, you wish to convert
list_1 = [1,2,5] to list_1 = [1,3,5]
The line which is not giving the desired result is:
list_1[i-1] += 2
The first time the for loop iterates, it generates list_1 = [3,2,5].
The second time it iterates, it generates list_1 = [3,4,5].
Change the line:
list_1[i-1] += 2
to:
list_1[i] = list_1[i-1] + 2
Update:
You said if the difference is less than 2, you wish to make the change.
Consider changing the if not htl ==2: condition to if htl < 2. This will then catch the situation where you have two consecutive elements which are equal. It also reads better.
Update 2:
In order to catch an error where your list has only zero or one elements, I recommend you place a condition before the loop. if len(list_1) > 1: would be a good place to start, otherwise the indexing will raise an IndexError.
I'm not sure to have totally understand what you want to do but first, to fixe you output probleme change :
list_1[i-1] += 2
by
list_1[i-1] += 2
and put your print outside of the for like that :
for i in range(1, len(list_1)):
htl = list_1[i]-list_1[i-1]
if not htl == 2:
list_1[i-1] += 1
print(list_1[i-1])
print(list_1[i-1])
Hope that can help you.
Here's my current code:
def even(x):
if x % 2 == 0:
even = True
else:
even = False
if even is True:
print("Even")
if even is False:
print("Odd")
N=[1,3,2,4]
for x in N:
even(x)
As it is the function takes each input and prints whether it's Even or Odd, very basic.
I gave myself the objective of writing a function/script that will take a list of numbers and spit out something like: "There are 15 even numbers and 8 odd numbers." However, I'm having trouble understanding how to count up a running total of how many times my variable "even" is True or False. Furthermore I don't understand how to then use that variable outside the function. So far my best attempts result in an output like:
There were 1 Odd numbers
There were 1 Odd numbers
There were 1 Even numbers
There were 1 Even numbers
etc... for whatever is in list N.
Whereas what I want is:
There were 2 Odd numbers
There were 2 Even numbers
Can anyone help me learn how to do something like this?
You could use a Counter:
from collections import Counter
c = Counter(x % 2 == 0 for x in lst)
print "There are %d even numbers and %d odd numbers" % (c[True], c[False])
You can use sum() and map():
def even(x):
return (x % 2 == 0)
N = [1,3,2,4,6,8]
n_even = sum(map(even, N))
print(n_even)
# 4
Now even returns True (1) if the number is even and False (0) otherwise. Now simply sum it up and you have the times an even number occurred.
Additionally, you might want to define n_odd as
n_odd = len(N) - n_even
I am trying to better understand list comprehension in Python. I completed an online challenge on codewars with a rather inelegant solution, given below.
The challenge was:
Given a list of even numbers and one odd, return the odd
Given a list of odd numbers and one even, return the even
My (inelegant) solution to this was:
def find_outlier(integers):
o = []
e = []
for i in integers:
if i % 2 == 0:
e.append(i)
else:
o.append(i)
# use sums to return int type
if len(o) == 1:
return sum(o)
else:
return sum(e)
Which works fine, but seems to be pretty brute force. Am I wrong in thinking that starting (most) functions with placeholder lists like o and e is pretty "noob-like"?
I would love to better understand why this solution works for the odd list, but fails on the even list, in an effort to better understand list comprehension:
def find_outlier(integers):
if [x for x in integers if x % 2 == 0]:
return [x for x in integers if x % 2 == 0]
elif [x for x in integers if x % 2 != 0]:
return [x for x in integers if x % 2 != 0]
else:
print "wtf!"
o = [1,3,4,5]
e = [2,4,6,7]
In[1]: find_outlier(o)
Out[1]: [4]
In[2]: find_outlier(e)
Out[2]: [2, 4, 6]
Where Out[2] should be returning 7.
Thanks in advance for any insights.
Your attempt fails because the first if is always going to be true. You'll always have a list with at least 1 element; either the odd one out is odd and you tested a list with all even numbers, otherwise you have a list with the one even number in it. Only an empty list would be false.
List comprehensions are not the best solution here, no. Try to solve it instead with the minimum number of elements checked (the first 2 elements, if they differ in type get a 3rd to break the tie, otherwise iterate until you find the one that doesn't fit in the tail):
def find_outlier(iterable):
it = iter(iterable)
first = next(it)
second = next(it)
parity = first % 2
if second % 2 != parity:
# odd one out is first or second, 3rd will tell which
return first if next(it) % 2 != parity else second
else:
# the odd one out is later on; iterate until we find the exception
return next(i for i in it if i % 2 != parity)
The above will throw a StopIteration exception if there are either fewer than 3 elements in the input iterable, or there is no exception to be found. It also won't handle the case where there is more than one exception (e.g. 2 even followed by 2 odd; the first odd value would be returned in that case).
What are the shortcomings of this response (which is at the top of the solution stack on this particular challenge)?
def find_outlier(int):
odds = [x for x in int if x%2!=0]
evens= [x for x in int if x%2==0]
return odds[0] if len(odds)<len(evens) else evens[0]
The most efficient answer is going to get a little ugly.
def f(in_list):
g = (i for i in in_list)
first = next(g)
second = next(g) #The problem as described doesn't make sense for fewer than 3 elements. Let them handle the exceptions.
if first%2 == second%2:
a = first%2
for el in g:
if el%2 != a:
return el
else:
third = next(g)
if third%2 == first%2:
return second
else:
return first
except ValueError('Got a bad list, all evens or all odds')
my while code:
i=0
a = range(100)
while i < range(100):
print i
i += 9
this goes into an infinite loop...may i know why?
is it because an integer is compared to the list?
but what happens when i becomes greater than 99?
shouldnt it come out of the while loop?
below code works fine as expected:
i=0
a = range(100)
a_len = len(a)
while i < a_len:
print i
i += 9
Sadly in Python 2.x, an int is always less than a list (even if that list is empty).
>>> 9 < []
True
What you want to be doing is using the 3-argument form of range so you have a start, a stop and a step, eg:
for i in range(0, 100, 9):
print i
range(100) is a list of integers from 1 to 100 over which you are supposed to iterate. So, len(range(100) = 100. In python 2.x, a list is always greater than an integer. A very simple way to fix this problem is:
i=0
while i < 100: # instead of range(100)
print i
i += 9