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)
Related
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.
here is the recursion code I am trying to change it to tail recursion
def stairClimb(n):
if n <= 3:
WaysToClimb = [1, 2, 4]
return WaysToClimb[n - 1]
else:
return stairClimb(n - 1) + stairClimb(n - 2) + stairClimb(n - 3)
When a procedure can recur multiple times per procedure application, to achieve a tail call, we must somehow sequence the multiple recursive calls
Using a technique called continuation-passing style, we can add a second parameter to our function that tells our function what the next step of our computation should be
A simple CPS conversion looks like this
def my_func (x):
return x
def my_cps_func (x, k)
# k represents the "next step"
return k (x)
Python has neat features tho, so we can write our function to support both direct style and continuation-passing style. We do this by assigning a default function as the continuation – we'll use this technique more below, so make sure you understand it here first
# by default, pass x thru untouched
# this is known as the "identity" function
def add (x, y, k = lambda x: x):
return k (x + y)
# direct style
print (add (2, 3)) # 5
# continuation-passing style
add (2, 3, print) # 5
# direct and CPS mixed! invent your own freedom
print (add (2, 3, lambda sum: add (sum, sum))) # 10
Your stair_climb is like a 3-fibonacci procedure (sometimes called "tribonacci") only yours uses a unique (1,2,4) seed instead of a more traditional (0,0,1) seed – we'll show tribonacci converted to CPS then we'll look at your procedure after that
def tribonacci (n, k = lambda x: x):
if n == 0:
return k (0)
elif n == 1:
return k (0)
elif n == 2:
return k (1)
else:
return tribonacci (n - 1, lambda a:
tribonacci (n - 2, lambda b:
tribonacci (n - 3, lambda c:
k (a + b + c))))
for x in range (1,10):
print (tribonacci (x))
# 0
# 1
# 1
# 2
# 4
# 7
# 13
# 24
# 44
But the time complexity of that function is O (3n) - since lambdas can abstract any number of values, this can be massively optimized by using a multi-parameter lambda – here we compute the same answer in O (n) where lambda a, b, c: ... represents our "seed"
# by default, return the first value of the seed
def tribonacci (n, k = lambda a, b, c: a):
if n == 0:
# base seed values
return k (0, 0, 1)
else:
# the next seed (this is our "next step")
return tribonacci (n - 1, lambda a, b, c:
# new seed
# b is the "next a"
# c is the "next b"
# the sum of each is the "next c"
k (b, c, a + b + c))
for x in range (1,10):
print (tribonacci (x))
# 0
# 1
# 1
# 2
# 4
# 7
# 13
# 24
# 44
All we have to do is change the k (0, 0, 1) seed to k (1, 2, 4)
def stair_climb (n, k = lambda a, b, c: a):
if n == 0:
return k (1, 2, 4)
else:
return stair_climb (n - 1, lambda a, b, c:
k (b, c, a + b + c))
for x in range (1,10):
print (stair_climb (x))
# 2
# 4
# 7
# 13
# 24
# 44
# 81
# 149
# 274
And yep, if you look at each line, every procedure application is in tail position
def stair_climb (n, k = lambda a, b, c: a):
if n == 0:
# tail
return k (1, 2, 4)
else:
# tail
return stair_climb (n - 1, lambda a, b, c:
# tail
k (b, c, a + b + c))
But you have a bigger problem – Python doesn't have tail call elimination
print (stair_climb (1000))
# RecursionError: maximum recursion depth exceeded in comparison
No worries, once you're using continuation-passing style, there's all sorts of ways around that
use accumulator:
def stairClimb(n, acc, acc1, acc2):
if n == 3:
return acc2
else:
return stairClimb(n-1, acc1, acc2, acc+acc1+acc2)
and call it with the initial numbers:
stairClimb(n, 1, 2, 4)
So, our teacher gave us an assignment to find three integers a, b c. They are in all between 0 and 450 using Python.
a = c + 11 if b is even
a = 2c-129 if b is odd
b = ac mod 2377
c = (∑(b-7k) from k = 0 too a-1) +142 (Edited. I wrote it wrong. Was -149)
I tired my code that looks like this: (Still a newbie. I guess a lot of my code is wrong)
for a, b, c in range(0, 450):
if b % 2 == 0:
a = c + 11
else:
a = 2 * c - 129
b = (a * c) % 2377
c = sum(b - 7 * k for k in range(0, a - 1))
but I get the error:
for a, b, c in range(0, 450):
TypeError: 'int' object is not iterable
What am I doing wrong and how can I make it check every number between 0 and 450?
The answers by Nick T and Eric hopefully helped you solve your issue with iterating over values of a, b, and c. I would like to also point out that the way you're approaching this problem isn't going to work. What's the point of iterating over various values of a if you're going to re-assign a to something anyway at each iteration of the loop? And likewise for b and c. A better approach involves checking that any given triple (a, b, c) satisfies the conditions given in the assignment. For example:
from itertools import product, tee
def test(a, b, c):
flags = {'a': False,
'b': False,
'c': False}
if (b % 2 == 0 and a == c+11) or (b % 2 == 1 and a == 2*c-129):
flags['a'] = True
if b == (a * c) % 2377:
flags['b'] = True
if c == sum(b - 7*k for k in range(a-1)) - 149:
flags['c'] = True
return all(flags.values()) # True if zero flags are False
def run_tests():
# iterate over all combinations of a=0..450, b=0..450, c=0..450
for a, b, c in product(*tee(range(451), 3)):
if test(a, b, c):
return (a, b, c)
print(run_tests())
NOTE: This is a slow solution. One that does fewer loops, like in glglgl's answer, or Duncan's comment, is obviously favorable. This is really more for illustrative purposes than anything.
import itertools
for b, c in itertools.product(*[range(450)]*2):
if b % 2 == 0:
a = c + 11
else:
a = 2 * c - 129
derived_b = (a * c) % 2377
derived_c = sum(b - 7 * k for k in range(0, a - 1))
if derived_b == b and derived_c == c:
print a, b, c
You need to nest the loops to brute-force it like you are attempting:
for a in range(451): # range(450) excludes 450
for b in range(451):
for c in range(451):
...
It's very obviously O(n3), but if you want a quick and dirty answer, I guess it'll work—only 91 million loops, worst case.
The stuff with [0, 450] is just as a hint.
In fact, your variables are coupled together. You can immediately eliminate at least one loop directly:
for b in range(0, 451):
for c in range(0, 451):
if b % 2: # odd
a = 2 * c - 129
else:
a = c + 11
if b != (a * c) % 2377: continue # test failed
if c != sum(b - 7 * k for k in range(a)): continue # test failed as well
print a, b, c
should do the job.
I won't post full code (after all, it is homework), but you can eliminate two of the outer loops. This is easiest if you iterate over c.
You code should then look something like:
for c in range(451):
# calculate a assuming b is even
# calculate b
# if b is even and a and b are in range:
# calculate what c should be and compare against what it is
# calculate a assuming b is odd
# calculate b
# if b is odd and a and b are in range:
# calculate what c should be and compare against what it is
Extra credit for eliminating the duplication of the code to calculate c
a = c + 11 if b is even
a = 2c-129 if b is odd
b = ac mod 2377
c = (∑(b-7k) from k = 0 to a-1) +142
This gives you a strong relation between all 3 numbers
Given a value a, there are 2 values c (a-11 or (a+129)/2), which in turn give 2 values for b (ac mod 2377 for both values of c, conditioned on the oddity of the result for b), which in turn gets applied in the formula for validating c.
The overall complexity for this is o(n^2) because of the formula to compute c.
Here is an implementation example:
for a in xrange(451):
c_even = a - 11
b = (a*c_even) % 2377
if b % 2 == 0:
c = sum(b - 7 * k for k in range(a)) + 142
if c == c_even:
print (a, b, c)
break
c_odd = (a+129)/2
b = (a*c_odd) % 2377
if b % 2 == 1:
c = sum(b - 7 * k for k in range(a)) + 142
if c == c_odd:
print (a, b, c)
break
def g(n):
"""Return the value of G(n), computed recursively.
>>> g(1)
1
>>> g(2)
2
>>> g(3)
3
>>> g(4)
10
>>> g(5)
22
"""
if n<=3:
return n
else:
return g(n-1)+2*g(n-2)+3*g(n-3)
How do I convert this to an iterative function? Until now, I didn't realize that writing a recursive function is sometimes easier than writing an iterative one. The reason why it's so hard I think is because I don't know what operation the function is doing. In the recursive one, it's not obvious what's going on.
I want to write an iterative definition, and I know I need to use a while loop, but each time I try to write one either I add additional parameters to g_iter(n) (when there should only be one), or I make a recursive call. Can someone at least start me off on the right path? You don't have to give me a complete solution.
FYI: We have not learned of the all too common "stack" I'm seeing on all these pages. I would prefer to stay away from this.
def g_iter(n):
"""Return the value of G(n), computed iteratively.
>>> g_iter(1)
1
>>> g_iter(2)
2
>>> g_iter(3)
3
>>> g_iter(4)
10
>>> g_iter(5)
22
"""
"*** YOUR CODE HERE ***"
def g(n):
if n <= 3:
return n
a, b, c = 1, 2, 3
for i in range(n - 3):
a, b, c = b, c, c + 2 * b + 3 * a
return c
UPDATE response to comment, without using for loop.
def g(n):
if n <= 3:
return n
a, b, c = 1, 2, 3
while n > 3:
a, b, c = b, c, c + 2 * b + 3 * a
n -= 1
return c
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)