Making Range Function Act Over Given Values in Python - python

I would like to know if there is a way to make the range function act only over some given values.
I'm trying to write some code for Problem 2 of Project Euler where I must find the sum of the even-valued terms of the Fibonacci sequence whose values do not exceed 4,000,000.
My code at the moment looks like this:
#Fibonacci Even Sum
even_sum = 0
def fib(n):
a, b = 1,2
while a < n:
print (a)
a, b = b, a + b
print ()
return a
for i in range(fib(4000000)):
if i % 2 == 0:
even_sum = i + even_sum
print (even_sum)
The problem seems to be that my code adds up all the even numbers up to 3524578, not just the even Fibonacci numbers. How can I change this?
Many thanks !

You should use a generator function, range() does not suit your problem. You can convert your fib function to a generator by giving yield a inside the while loop, that would make the function keep spitting out fibonacci numbers till n and you can find sum like that.
Example of generator -
>>> def fib(n):
... a, b = 1,2
... while a < n:
... yield a
... a, b = b, a+b
...
>>>
>>>
>>>
>>> for i in fib(200):
... print(i)
...
1
2
3
5
8
13
21
34
55
89
144
you can make similar changes to your function.
Code would look like -
even_sum = 0
def fib(n):
a, b = 1,2
while a < n:
print (a)
a, b = b, a + b
yield a
for i in fib(4000000):
if i % 2 == 0:
even_sum = i + even_sum
print (even_sum)

Related

Sum of a range in Python [duplicate]

This question already has answers here:
Where to use the return statement with a loop?
(2 answers)
Closed 26 days ago.
I have to find the sum of a range between the values a and b, although either can be a negative number. If they are the same number I should just return that number. A complete beginner here. Stuck on a Code-Wars kata.
Apparently, my code returns None. I don't necessarily want the solution to the problem. I more want to know why my code is wrong. (The first line of the code is given)
def get_sum(a,b):
if a == b:
return a
num = 0
if a > b:
for i in range(a, b):
num += i
return num
elif a < b:
for i in range(b, a):
num += i
return num
I think there is an indentation issue located on the return instruction and also a problem on the sign greater than.
def get_sum(a,b):
if a == b:
return a
num = 0
if a < b:
for i in range(a, b):
num += i
return num
elif a > b:
for i in range(b, a):
num += i
return num
You could also use built-in functions to make it faster and more concise
sum(range(a, b))
Thinking about the problem itself, rather than your particular function, you could use Gauss's method: reverse the sequence, add it to itself, and the total will be twice the sum sought.
However, each term is now equal, so you have reduced the question to a multiplication.
1 + 2 + 3 + 4
4 + 3 + 2 + 1
-------------
5 + 5 + 5 + 5 = 20
20/2 = 10
In Python this would be:
def get_sum(small, large):
return int((large - small + 1) * (small + large) / 2)
You can use the gauss formula:
n(n+1)/2
https://letstalkscience.ca/educational-resources/backgrounders/gauss-summation
def gauss(n):
return (abs(n)*(abs(n)+1)/2)* (-1 if n < 0 else 1)
def sum_between(a, b):
a,b = min(a, b), max(a, b)
return gauss(b) - gauss(abs(a))
You can actually transform sum_between in a single formula with a bit of algebra.
For the same number then just add an if
There's always
def get_sum(a, b):
return sum(range(min(a, b), max(a, b)))
add 1 to the lower-bound if you want numbers strictly between, or add 1 to the upper bound if you want it included in the sum.
It might not be as pedagogical as writing it out yourself and it doesn't rely on math(s).

Does the number belong in the fibonacci sequence?

A Ke-number is an integer 10≤n≤99 such that, if we start a Fibonacci sequence with its digits, the sequence contains n.
For example, 47 is a Ke-number because the sequence starts like this: 4,7,11,18,29,47, coming to the number itself.
I'm trying to define the recursive function ke_number that takes a two-digit integer and checks if it is a Ke-number. (True or False)
I got it to work like this:
def ke_number(n):
n1 = int(str(n)[0])
n2 = int(str(n)[1])
return n in [fib(i,n1,n2) for i in range(1,100)]
def fib(n, a, b):
if n==0 or n==1:
return b
return fib(n-1, b, a+b)
But as you can see, it's not just one function, it's two.
How can I transform this into just one recursive function?
Recursive solution:
Try it online!
def ke_number(n, a = None, b = None):
if a is None:
return ke_number(n, n // 10, n % 10)
if a < n:
return ke_number(n, b, a + b)
return a == n
print(ke_number(47))
print(ke_number(46))
Output:
True # for 47
False # for 46
With function above if you do:
Try it online!
for i in range(10, 100):
if ke_number(i):
print(i)
you'll get all Ke numbers:
14
19
28
47
61
75
As there is already a recursive solution posted by Arty, here is a non recursive one that might be handy (easier to read and does not come with the problems recursive function calls can have, but that really depends on what you want to do in the end)
def ke_test(n):
a, b = divmod(n, 10)
while b < n:
a, b = b, a+b
return b == n

Define a function to choose 2 bigger number out of 3 numbers then sum the square of the 2 numbers

Define a function that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.
For example, given 6,7,8, the function that I defined should return 113
When I gave my code, it solves most of the problems but apparently there is some possibility that I haven't tried?? I think my code is flawed but not sure what other possibilities are there. Would really appreciate some help thank you so much!
def bigger_sum(a,b,c):
if(a+b>b+c):
return(a*a+b*b)
if(a+c>b+c):
return(a*a+c*c)
if(b+c>a+c):
return(b*b+c*c)
You can use min for this problem:
def big2_sqrsum(a,b,c):
x = min(a,b,c)
return (a*a + b*b + c*c) - (x*x)
print(big2_sqrsum(6,7,8))
Output:
113
Alternate solution with if-else
def big2_sqrsum2(a,b,c):
if a < b and a <c:
return b*b + c*c
elif b < a and b < c:
return a*a + c*c
elif c < a and c < b:
return a*a + b*b
Just check for the smallest number. That known, assign the values to two new variables that will hold the largest and second largest value and sum their squares.
Something like this :
big1 = 0
big2 = 0
if ([a is smallest]):
big1 = b
big2 = c
elif ([b is smallest]):
big1 = a
big2 = c
elif ([c is smallest]):
big1 = a
big2 = b
allows you to have only one place to calculate your formula :
return big1 * big1 + big2 * big2
Let's take a look at why your code is flawed. Given a comparison like if a + b > b + c:, the implication that both a and b are both greater than c is false. b can be the smallest number. All you know is that a > c, since you can subtract b from both sides of the inequality.
You need to find and discard the smallest number. The simplest way is to compute the minimum with min and subtract it off, as #Sociopath's answer suggests.
If you want to keep your if-elsestructure, you have to compare numbers individually:
if a > b:
n1= a
n2 = b if b > c else c
elif a > c:
n1, n2 = a, b
else:
n1, n2 = b, c
You can Simply Define Function With Using min()
def two_bigger_sum(num1,num2,num3):
min_num = min(num1,num2,num3) # it returns minimum number
return ((num1**2 + num2**2 + num3**2)-(min_num**2)) # num**2 = square of num
print(two_bigger_sum(6,7,8))
Output = 113
Sociopath's answer works, but is inefficient since it requires two extra floating point multiplies. If you're doing this for a large number of items, it will take twice as long! Instead, you can find the two largest numbers directly. Basically, we're sorting the list and taking the two largest, this can be directly as follows:
def sumsquare(a,b,c):
# Strategy: swap, and make sure c is the smallest by the end
if c > b:
b, c = c, b
if c > a:
a, c = c, a
return a**2 + b**2
# Test:
print(sumsquare(3,1,2))
print(sumsquare(3,2,1))
print(sumsquare(1,2,3))
print(sumsquare(1,3,2))
print(sumsquare(2,1,3))
print(sumsquare(2,3,2))
I have tried to use list comprehension & list slicing with sorting method.
def b2(l):
return sum([x**2 for x in sorted(l)[1:]])
print(b2([1,2,3]))
OP:-
13

Convert this function from recursive to iterative

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

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