Python declaring multiple variable confusion - python

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

Related

How to find exponent of pow(a,b,c) in python

pow(a,x,c) operator in python returns (a**x)%c . If I have values of a, c, and the result of this operation, how can I find the value of x?
Additionally, this is all the information I have
pow(a,x,c) = pow(d,e,c)
Where I know the value of a,c,d, and e.
These numbers are very large (a = 814779647738427315424653119, d = 3, e = 40137673778629769409284441239, c = 1223334444555556666667777777) so I can not just compute these values directly.
I'm aware of the Carmichael's lambda function that can be used to solve for a, but I am not sure if and/or how this applies to solve for x.
Any help will be appreciated.
As #user2357112 says in the comments, this is the discrete logarithm problem, which is computationally very difficult for large c, and no fast general solution is known.
However, for small c there are still some things you can do. Given that a and c are coprime, there is an exponent k < c such that a^k = 1 mod c, after which the powers repeat. Let b = a^x. So, if you brute force it by calculating all powers of a until you get b, you'll have to loop at most c times:
def do_log(a, b, c):
x = 1
p = a
while p != b and p != 1:
x += 1
p *= a
p %= c
if p == b:
return x
else:
return None # no such x
If you run this calculation multiple times with the same a, you can do even better.
# a, c constant
p_to_x = {1: 0}
x = 1
p = a
while p != 1:
p_to_x[p] = x
x += 1
p *= a
p %= c
def do_log_a_c(b):
return p_to_x[b]
Here a cache is made in a loop running at most c times and the cache is accessed in the log function.

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

My homework is to find out the line by line explanation of this code

When i run this code it doesn't have an output, and please can you explain the purpose of this code and give a line-by-line explanation of how it achieves its purpose.
def mystery(n):
a, b = 0, 1
while a < n
print (a)
a, b = b, a + b
I have also figured out how to make it output
You add a line which is mystery(n) e.g. mystery(200)
I think it is like this:
• The first line defines a function with one parameter. The word “def” presents a function
definition. The function “def” must be followed by the function name e.g. mystery.
• The second line contains a multiple assignment. It is saying that the variable “a” is equal
to 0 and “b” is equal to 1
• The function defines the value of “n”. On the third line “n” is undefined.
• The fourth line is to print (a)
• The fifth line makes
This code is a Fibonacci series generator upto n. The only error is the missing colon (:) after while statement. It starts with a=0 abd b=1: compares a < n; prints a if comparison generates True; assigns b to a and increments b by a; continues while loop until comparison generates False:
>>> def mystery(n):
... a, b = 0, 1
... while a < n:
... print (a)
... a,b = b,a+b
...
>>> mystery (10)
0
1
1
2
3
5
8
# This is a method.
# You can call this method to its logic. (sea last line)
# N would be the maximum value
def mystery(n):
# This is the same as:
# a = 0 Asign a to 0
# b = 1 Asign b to 1
a, b = 0, 1
# Do the following until a is the same or bigger than n.
while a < n:
# Print the value of a
print a
# This is the same as:
# temp = a
# a = b
# b = a + b
# Example: a =1 and b =2
# temp = a
# a = 2
# b = temp + 2
a, b = b, a + b
# Calling the method with value 10
# you first have to call this before it executes
mystery(10)
Output:
0
1
1
2
3
5
8
This is called fibonacci
Instead of defining the value you want the Fibonacci sequence for inside of the code, why not change the code to:
def mystery(n):
a, b = 0, 1
while a < n:
print (a)
a, b = b, a + b
mystery(int(input("Insert A Number: ")))
This will allow the user to input a value of which, the Fibonacci sequence will be shown.

Python: Usage of Variables and their difference ("a, b = 0, 1" VS "a = 0", "b = 1") [duplicate]

This question already has answers here:
Python - Difference between variable value declaration on Fibonacci function
(4 answers)
Closed 8 years ago.
I was looking at the Python Manual and found this snippet for a Fibonacci-Number generator:
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while b < n:
print(b, end=' ')
a, b = b, a+b
print()
The output is dependent on n and returns a valid Fibonacci sequence.
If you remodel this to use the variables "a" and "b" seperately like so:
def fib(n): # write Fibonacci series up to n
a = 0
b = 1
while b < n:
print(b, end=' ')
a = b
b = a+b
print()
then it will print a number sequence that increments by the power of 2 (e.g. 1, 2, 4, 8, 16 and so on).
So I was wondering why that happens? What is the actual difference between the two uses of variables?
Doing:
a, b = b, a+b
is equivalent to:
temp = a
a = b
b += temp
It lets you simultaneously do two calculations without the need of an intermediate/temporary variable.
The difference is that in your second piece of code, when you do the second line b = a+b, you have already modifed a in the previous line which is not the same as the first piece of code.
Examples
>>> a = 2
>>> b = 3
>>> a,b
2 3
>>> a,b = b,a
>>> a,b
3 2
On the other hand, if you use the second approach shown in your question:
>>> a = 2
>>> b = 3
>>> a,b
2 3
>>> a = b
>>> b = a
>>> a,b
3 3
In
a, b = b, a+b
the right-hand expressions are evaluated first, and their results are assigned to a and b. This is similar to the following:
_new_a = b
_new_b = a+b
a = _new_a
b = _new_b
On the other hand, in
a = b
b = a+b
you are modifying a before adding it to b. This is equivalent to
a, b = b, b+b
which explains where the powers of two are coming from.

Error in for loop. (Finding three integers)

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

Categories