problem with arrays and operations result beign asaigned to values - python

Here is the python code :
x=[2, 3, 5, 7]
for i in range(1, 5000):
if i%2:
if i%3:
if i%5:
if i%7:
x.append(i)
x.remove(1)
a = 6
b = 2
for i in range(0, 10):
a = x[a - b]
b = x[a] - x[b]
I get an IndexError: list index out of range for some reason, even though x[] is 1360 and a is just 6 while b is 2 so I dont know why it is happening. Any help would be nice.
I am using the python shell. Would that be a problem?

The problem of your code is your logic in the for loop.
You see:-
a = 6
b = 2
for i in range(0, 10):
a = x[a - b]
b = x[a] - x[b]
Yes a was 6 & b was 2, but then when you enter your for loop for the first time,
a's value is
x[a-b] which is x[6-2]
i.e. x[4] which gives you 11
so a's value is 11, likewise for b,
b = x[a] - x[b] # which translates to x[11] - x[2]
which becomes b=32 & the loop goes on jumping/changing the values of a & b which leads you to IndexError: list index out of range which is expected.
Try executing your program in pycharm & debug it, you would understand it better, or maybe just put some print statements.
I could not type so much in a comment, hence posted it as an answer.

Related

Iteration for Recurrent Problem with Python

I am asked to find the 30th of a recurrence series, following the equation x(n) = 2*x(n-1) - x(n-2) for n >= 3, and x(1) = 0 and x(2) = 1.
Following the logic of fibonacci iteration, I have come up with the following code:
def loop(n):
a = 0
b = 1
for i in range(30):
a, b = b, 2 * b - a
return a
Suiting in loop(30), I am returned 30, but I know mathematically that the answer should be 29. The code seems to be going one step ahead. Can anyone help point out what is incorrect in my code?
You should only run the loop n - 1 times. Because the assignment a = 0 initializes x1. Then after each loop, a is assigned by the next value (from x2)
def loop(n):
a = 0
b = 1
for i in range(n - 1):
a, b = b, 2*b - a
return a
print(loop(30))
# 29
You can notice that for the first time value of a=1 ( a=b=1;), According to the condition value of a is incremented by 1 ( a=b when b=2*b-1) so the output will be n on next nth iterations.;

Is there a Python function that does what mapply do in R

Is there a function in Python that can do what Mapply do in R?
Basically I have a list of n inputs(each entry is a dataframe) for a function and corresponding lists(each list has the length of n) of parameters.
In each parameter lists, the position of each parameter corresponds to the respective position of input in the input list.
Now I wish to obtain the result in the exact order of the way I put my input, either in the form of a list with each element a dataframe(or matrix or whatever) or just one dataframe with all result appended. This is easily achievable in R using Mapply, but in python, I haven't got the luck to find any function that does the trick.
I haven't try this but one of the solution that i thought of is to pd.concat all lists(including input list and parameter lists) I got into one bulky list by column and apply the function to each row where I'll extract each element of the row to fill the function.
This might work but it would look quite stupid if there is actually one-line solution.
This is how I would deal with the problem in R:
result <- mapply(FUN = function(input, parameter1, parameter2) function_of_interest(input, parameter1, parameter2), input = input_list, parameter1 = parameter1_list, parameter2 = parameter2_list,... )
If I understand the question correctly, this example of mapply in R:
A <- c(1, 2, 3)
B <- c(2, 3, 4)
my_multiplication <- function(x,y){return(x*y)}
C <- mapply(my_multiplication, A, B)
could be roughly equivalent to this Python code:
a = [1, 2, 3]
b = [2, 3, 4]
def my_multiplication(x, y):
return x * y
c = map(my_multiplication, a, b)
The c is now a so called iterator. If I oversimplify, c can be viewed as a function that returns:
a[0] * b[0] on first call,
a[1] * b[1] on second call,
a[2] * b[2] on third (and last) call
i = 0
message = 'a[{}] * b[{}] = {} * {} = {}'
for result in c:
print(message.format(i, i ,a[i], b[i], result))
i += 1
prints
a[0] * b[0] = 1 * 2 = 2
a[1] * b[1] = 2 * 3 = 6
a[2] * b[2] = 3 * 4 = 12
My answer seems to be a modification of the answer given by #Paolo42, which just wraps the "map" function with a call to "list" to get rid of the loop:
>>> list(map(my_multiplication, A, B) )
[2, 6, 12]
I also liked the list comprehension solution given by #Alexander, but I also appreciate the comment from #Paolo42.

Python declaring multiple variable confusion

I would like to know why this code is giving me two different solution:
a = 0
b = 1
solution = 0
while b <= 4000000:
if b % 2 == 0:
solution += b
a, b = b, a + b
print(solution)
in this case the solution is 4613732. However when I try this code:
a = 0
b = 1
solution = 0
while b <= 4000000:
if b % 2 == 0:
solution += b
a = b
b = a + b
print(solution)
the solution is 4194302
Any suggestions?
The difference explained
Because you write:
a = b
b = a + b
In your second approach. That means that after the first line, a has the value of b. And the second line will produce b = a + b = b + b so two times b. In other words, the second one will actually walk through the powers of two.
That is not happening in the first approach, since you write:
a, b = b, a + b
As a result you first construct a tuple (b,a+b) (with a and b the old values). Next you unpack that tuple into a and b again. But you first evaluated a + b with the old values. That is the essential difference.
More efficient approach
You want to sum up the even Fibonacci numbers. You can however to this more efficiently. If you do an analysis on the Fibonacci sequence, you will find out that it is structured:
o o e o o e o o e ...
with o being an odd number, and e being an even number. So you can simply work with hops of three, like:
a = 1
b = 2
solution = 0
while b <= 4000000:
solution += b
a,b = a+2*b,2*a+3*b
print(solution)
Here we thus save on iterations and on checks whether b is even: we simply know that it is always even.
When using timeit (with Python 3.5.3 and GCC 6.3.0 on linux), we obtain the following results:
original 3.4839362499988056
optimized 1.5940769709995948 45.755%
So the average runtime of the optimized program is about half of the original one.
Simply because, all expressions at the right side of the assignment operator gets evaluated first.
So let's say you have the code below:
a = 5
b = 7
a, b = b, a + b
You expect a to be assigned with the value 7 and then b to be assigned with the value 14, the sum of a and b using the new value of a.
In fact, on the right side of the = operator, b is evaluated to 7 and a+b is evaluated to 12
a, b = 7, 12

Looping through an interval in either direction

Suppose you want to loop through all integers between two bounds a and b (inclusive), but don't know in advance how a compares to b. Expected behavior:
def run(a, b):
if a < b:
for i in range(a, b + 1):
print i,
elif a > b:
for i in range(a, b - 1, -1):
print i,
else:
print a
print
run(3, 6)
run(6, 3)
run(5, 5)
Result:
3 4 5 6
6 5 4 3
5
Is there a more elegant solution? The following is more concise, but fails when a == b:
def run(a, b):
for i in range(a, b + cmp(b, a), cmp(b, a)):
print i,
print
run(3, 6)
run(6, 3)
run(5, 5)
Result:
3 4 5 6
6 5 4 3
(...)
ValueError: range() step argument must not be zero
This will work for all cases:
def run(a, b):
"""Iterate from a to b (inclusive)."""
step = -1 if b < a else 1
for x in xrange(a, b + step, step):
yield x
The insight that led me to this formulation was that step and the adjustment to b were the same in both of your cases; once you have an inclusive end you don't need to special-case a == b. Note that I've written it as a generator so that it doesn't just print the results, which makes it more use when you need to integrate it with other code:
>>> list(run(3, 6))
[3, 4, 5, 6]
>>> list(run(6, 3))
[6, 5, 4, 3]
>>> list(run(5, 5))
[5]
Using generator delegation in Python 3.3+ (see PEP-380), this becomes even neater:
def run(a, b):
"""Iterate from a to b (inclusive)."""
step = -1 if b < a else 1
yield from range(a, b + step, step)
You almost got it yourself:
def run(a, b):
for i in range(a, b + (cmp(b, a) or 1), cmp(b, a) or 1):
print i,
print
works just fine... when cmp(b, a) evaluates to 0 (when they are equal), it defaults to 1, although I'd definitely consider Jon's answer more elegant, you were on the right track! I make extensive use of python's logical or when doing comparisons like this:
(func() or default) is very useful for any function that returns a zero that you want to overwrite. Python evaluates it as False or True and returns default.
range(min((a,b)), max((a,b))+1)

Sum of even integers from a to b in Python

This is my code:
def sum_even(a, b):
count = 0
for i in range(a, b, 1):
if(i % 2 == 0):
count += [i]
return count
An example I put was print(sum_even(3,7)) and the output is 0. I cannot figure out what is wrong.
Your indentation is off, it should be:
def sum_even(a, b):
count = 0
for i in range(a, b, 1):
if(i % 2 == 0):
count += i
return count
so that return count doesn't get scoped to your for loop (in which case it would return on the 1st iteration, causing it to return 0)
(And change [i] to i)
NOTE: another problem - you should be careful about using range:
>>> range(3,7)
[3, 4, 5, 6]
so if you were to do calls to:
sum_even(3,7)
sum_even(3,8)
right now, they would both output 10, which is incorrect for sum of even integers between 3 and 8, inclusive.
What you really want is probably this instead:
def sum_even(a, b):
return sum(i for i in range(a, b + 1) if i % 2 == 0)
Move the return statement out of the scope of the for loop (otherwise you will return on the first loop iteration).
Change count += [i] to count += i.
Also (not sure if you knew this), range(a, b, 1) will contain all the numbers from a to b - 1 (not b). Moreover, you don't need the 1 argument: range(a,b) will have the same effect. So to contain all the numbers from a to b you should use range(a, b+1).
Probably the quickest way to add all the even numbers from a to b is
sum(i for i in xrange(a, b + 1) if not i % 2)
You can make it far simpler than that, by properly using the step argument to the range function.
def sum_even(a, b):
return sum(range(a + a%2, b + 1, 2))
You don't need the loop; you can use simple algebra:
def sum_even(a, b):
if (a % 2 == 1):
a += 1
if (b % 2 == 1):
b -= 1
return a * (0.5 - 0.25 * a) + b * (0.25 * b + 0.5)
Edit:
As NPE pointed out, my original solution above uses floating-point maths. I wasn't too concerned, since the overhead of floating-point maths is negligible compared with the removal of the looping (e.g. if calling sum_even(10, 10000)). Furthermore, the calculations use (negative) powers of two, so shouldn't be subject by rounding errors.
Anyhow, with the simple trick of multiplying everything by 4 and then dividing again at the end we can use integers throughout, which is preferable.
def sum_even(a, b):
if (a % 2 == 1):
a += 1
if (b % 2 == 1):
b -= 1
return (a * (2 - a) + b * (2 + b)) // 4
I'd like you see how your loops work if b is close to 2^32 ;-)
As Matthew said there is no loop needed but he does not explain why.
The problem is just simple arithmetic sequence wiki. Sum of all items in such sequence is:
(a+b)
Sn = ------- * n
2
where 'a' is a first item, 'b' is last and 'n' is number if items.
If we make 'a' and b' even numbers we can easily solve given problem.
So making 'a' and 'b' even is just:
if ((a & 1)==1):
a = a + 1
if ((b & 1)==1):
b = b - 1
Now think how many items do we have between two even numbers - it is:
b-a
n = --- + 1
2
Put it into equation and you get:
a+b b-a
Sn = ----- * ( ------ + 1)
2 2
so your code looks like:
def sum_even(a,b):
if ((a & 1)==1):
a = a + 1
if ((b & 1)==1):
b = b - 1
return ((a+b)/2) * (1+((b-a)/2))
Of course you may add some code to prevent a be equal or bigger than b etc.
Indentation matters in Python. The code you write returns after the first item processed.
This might be a simple way of doing it using the range function.
the third number in range is a step number, i.e, 0, 2, 4, 6...100
sum = 0
for even_number in range(0,102,2):
sum += even_number
print (sum)
def sum_even(a,b):
count = 0
for i in range(a, b):
if(i % 2 == 0):
count += i
return count
Two mistakes here :
add i instead of [i]
you return the value directly at the first iteration. Move the return count out of the for loop
The sum of all the even numbers between the start and end number (inclusive).
def addEvenNumbers(start,end):
total = 0
if end%2==0:
for x in range(start,end):
if x%2==0:
total+=x
return total+end
else:
for x in range(start,end):
if x%2==0:
total+=x
return total
print addEvenNumbers(4,12)
little bit more fancy with advanced python feature.
def sum(a,b):
return a + b
def evensum(a,b):
a = reduce(sum,[x for x in range(a,b) if x %2 ==0])
return a
SUM of even numbers including min and max numbers:
def sum_evens(minimum, maximum):
sum=0
for i in range(minimum, maximum+1):
if i%2==0:
sum = sum +i
i= i+1
return sum
print(sum_evens(2, 6))
OUTPUT is : 12
sum_evens(2, 6) -> 12 (2 + 4 + 6 = 12)
List based approach,
Use b+1 if you want to include last value.
def sum_even(a, b):
even = [x for x in range (a, b) if x%2 ==0 ]
return sum(even)
print(sum_even(3,6))
4
[Program finished]
This will add up all your even values between 1 and 10 and output the answer which is stored in the variable x
x = 0
for i in range (1,10):
if i %2 == 0:
x = x+1
print(x)

Categories