I have this problem but don't know where to start. The only thing I have in my mind is Fibonacci numbers and for loop (but don't know how to apply). It looks like Fibonacci but the first terms are different.
We have a sequence beginning with a then a+b. The 3rd number is
a+b+a, the 4th one is a+b+a+a+b. Which means that a number is
equal to the sum of 2 previous terms. (except the two first terms).
We need to find the index of the number given that the number is
exactly 100k. a and b are picked randomly. The program has to end by print(a,b,index)
So my problem is, I don't know how to choose a and b which can satisfy the 100k condition. For example:
If a == 35k and b == 20k, then the sequence would be like this:
35k, 55k, 90k, 145k and no 100k in the sequence.
So how to deal with this problem? Really appreciate!!
EDIT: this is a correction over my last answer
First write the difference equation according to the described conditions:
f[0] = a
f[1] = a + b
f[2] = f[1] + f[0]
= 2a + b = a + b + a
f[3] = f[2] + f[1] = f[1] + f[0] + f[1]
= 3a + 2b
= a + b + a + a + b
f[4] = f[3] + f[2]
= 3a + 2b + 2a + b = 5a + 3b
f[5] = f[4] + f[3]
= 5a + 3b + 3a + 2b = 8a + 5b
f[6] = f[5] + f[4]
= 8a + 5b + 5a + 3b = 13a + 8b
...
f[n] = f[n-1] + f[n-2]
We can actually simplify this problem if we separate a and b:
f_a[n] = a*(f[n-1] + f[n-2]) with f[0] = 1 and f[1] = 1
f_b[n] = b*(f[n-1] + f[n-2]) with f[0] = 0 and f[1] = 1
Now, if we calculate the solution to the diference equation we should obtain the following assuming that s=sqrt(5) that n \in N (is a natural number):
w1a = ((1+s)/2)ˆ{n+1}
w2a = ((1-s)/2)ˆ{n+1}
w1b = ((1+s)/2)ˆn
w2b = ((1-s)/2)ˆn
f_a[n] = (1/s) * [w1a - w2a] * a
f_b[n] = (1/s) * [w1b - w2b] * b
Simplifying:
l = (1+s)/2
g = (1-s)/2
f[n] = f_a[n] + f_b[n]
= (1/s) * [lˆn(al+b) - gˆn(ag+b)]
You can find more info on how to solve diference equations here: https://www.cl.cam.ac.uk/teaching/2003/Probability/prob07.pdf
You can implement these equations in a Python function to obtain any value of this function.
from math import sqrt
def f(n, a, b):
s = sqrt(5)
l = (1+s)/2
g = (1-s)/2
fn = (1/s) * ((a*l + b) * (l**n) - (a*g + b) * (g**n))
return int(round(fn, 0))
Searching for the index iteratively
You may now find the n which solves this equation for a particular f(n) if you apply the logarithmic function (see the section below). However, if time complexity is not an issue for you, and given that f[n] grows exponentially for n (meaning that you will not need to search much until 100k is reached or surpassed), you may also simply find the n which gives f[n] for a given a and b by doing the following search:
def search_index(a, b, value):
n = 0
while(True):
fn = f(n, a, b)
if fn == value:
return n
elif fn > value:
return -1
else:
n += 1
def brute_search(range_a, range_b, value):
for a in range(range_a + 1):
for b in range(range_b + 1):
if (a == 0) and (b == 0):
a = 1
res = search_index(a, b, value)
if res != -1:
return a, b, res
return -1
brute_search(1000, 1000, 100000)
>>> (80, 565, 12) # a = 80, b = 565 and n = 12
Through this (quite bad) method we find that for a=80 and b=565, n=12 will return f_n = 100k. If you would like to find all possible solutions for a range of values of a and b, you can modify brute_search in the following way:
def brute_search_many_solutions(range_a, range_b, value):
solutions = []
for a in range(range_a + 1):
for b in range(range_b + 1):
if (a == 0) and (b == 0):
a = 1
res = search_index(a, b, value)
if res != -1:
solutions.append((a, b, res))
return solutions
Analytical solution
Transforming the previous diference equation f_n so that now n is a function of a, b and f_n we obtain:
n \aprox log((f_n * s) / (a * l + b)) / log(l)
This result is an approximation, which may guide your search. You can use it in the following way:
def find_n(a, b, value):
s = sqrt(5)
l = (1+s)/2
g = (1-s)/2
return int(round(log(value * s / (a * l + b)) / log(l), 0))
def search(a, b, value):
n = find_n(a, b, value)
sol = f(n, a, b)
if sol == value:
return(a, b, n)
elif sol > value:
for i in range(n-1, 0, -1):
sol = f(i, a, b)
if sol == value:
return(a, b, i)
elif sol < value:
return(-1, 'no solution exits for a={} and b={}'.format(a, b))
else: # this should probably never be reached as find_n should
# provide an upper bound. But I still need to prove it
i = n
while(sol < value):
i += 1
sol = f(i, a, b)
if sol == value:
return(a, b, i)
elif sol > value:
return(-1, 'no solution exits for a={} and b={}'.format(a, b))
search(80, 565, 100000)
>>> (80, 565, 12) # a = 80, b = 565 and n = 12
NOTE: I would have loved to use mathematical notation here with LaTeX, but unfortunately I did not find an easy way to do it... Likely, this question would fit better Stack Exchange, than Stack overflow.
Related
The following code prints the pythagorean triplet if it is equal to the input, but the problem is that it takes a long time for large numbers like 90,000 to answer.
What can I do to optimize the following code?
1 ≤ n ≤ 90 000
def pythagoreanTriplet(n):
# Considering triplets in
# sorted order. The value
# of first element in sorted
# triplet can be at-most n/3.
for i in range(1, int(n / 3) + 1):
# The value of second element
# must be less than equal to n/2
for j in range(i + 1,
int(n / 2) + 1):
k = n - i - j
if (i * i + j * j == k * k):
print(i, ", ", j, ", ",
k, sep="")
return
print("Impossible")
# Driver Code
vorodi = int(input())
pythagoreanTriplet(vorodi)
Your source code does a brute force search for a solution so it's slow.
Faster Code
def solve_pythagorean_triplets(n):
" Solves for triplets whose sum equals n "
solutions = []
for a in range(1, n):
denom = 2*(n-a)
num = 2*a**2 + n**2 - 2*n*a
if denom > 0 and num % denom == 0:
c = num // denom
b = n - a - c
if b > a:
solutions.append((a, b, c))
return solutions
OP code
Modified OP code so it returns all solutions rather than printing the first found to compare performance
def pythagoreanTriplet(n):
# Considering triplets in
# sorted order. The value
# of first element in sorted
# triplet can be at-most n/3.
results = []
for i in range(1, int(n / 3) + 1):
# The value of second element
# must be less than equal to n/2
for j in range(i + 1,
int(n / 2) + 1):
k = n - i - j
if (i * i + j * j == k * k):
results.append((i, j, k))
return results
Timing
n pythagoreanTriplet (OP Code) solve_pythagorean_triplets (new)
900 0.084 seconds 0.039 seconds
5000 3.130 seconds 0.012 seconds
90000 Timed out after several minutes 0.430 seconds
Explanation
Function solve_pythagorean_triplets is O(n) algorithm that works as follows.
Searching for:
a^2 + b^2 = c^2 (triplet)
a + b + c = n (sum equals input)
Solve by searching over a (i.e. a fixed for an iteration). With a fixed, we have two equations and two unknowns (b, c):
b + c = n - a
c^2 - b^2 = a^2
Solution is:
denom = 2*(n-a)
num = 2*a**2 + n**2 - 2*n*a
if denom > 0 and num % denom == 0:
c = num // denom
b = n - a - c
if b > a:
(a, b, c) # is a solution
Iterate a range(1, n) to get different solutions
Edit June 2022 by #AbhijitSarkar:
For those who like to see the missing steps:
c^2 - b^2 = a^2
b + c = n - a
=> b = n - a - c
c^2 - (n - a - c)^2 = a^2
=> c^2 - (n - a - c) * (n - a - c) = a^2
=> c^2 - n(n - a - c) + a(n - a - c) + c(n - a - c) = a^2
=> c^2 - n^2 + an + nc + an - a^2 - ac + cn - ac - c^2 = a^2
=> -n^2 + 2an + 2nc - a^2 - 2ac = a^2
=> -n^2 + 2an + 2nc - 2a^2 - 2ac = 0
=> 2c(n - a) = n^2 - 2an + 2a^2
=> c = (n^2 - 2an + 2a^2) / 2(n - a)
DarrylG's answer is correct, and I've added the missing steps to it as well, but there's another solution that's faster than iterating from [1, n). Let me explain it, but I'll leave the code up to the reader.
We use Euclid's formula of generating a tuple.
a = m^2 - n^2, b = 2mn, c = m^2 + n^2, where m > n > 0 ---(i)
a + b + c = P ---(ii)
Combining equations (i) and (ii), we have:
2m^2 + 2mn = P ---(iii)
Since m > n > 0, 1 <= n <= m - 1.
Putting n=1 in equation (iii), we have:
2m^2 + 2m - P = 0, ax^2 + bx + c = 0, a=2, b=2, c=-P
m = (-b +- sqrt(b^2 - 4ac)) / 2a
=> (-2 +- sqrt(4 + 8P)) / 4
=> (-1 +- sqrt(1 + 2P)) / 2
Since m > 0, sqrt(b^2 - 4ac) > -b, the only solution is
(-1 + sqrt(1 + 2P)) / 2 ---(iv)
Putting n=m-1 in equation (iii), we have:
2m^2 + 2m(m - 1) - P = 0
=> 4m^2 - 2m - P = 0, ax^2 + bx + c = 0, a=4, b=-2, c=-P
m = (-b +- sqrt(b^2 - 4ac)) / 2a
=> (2 +- sqrt(4 + 16P)) / 8
=> (1 +- sqrt(1 + 4P)) / 4
Since m > 0, the only solution is
(1 + sqrt(1 + 4P)) / 4 ---(v)
From equation (iii), m^2 + mn = P/2; since P/2 is constant,
when n is the smallest, m must be the largest, and vice versa.
Thus:
(1 + sqrt(1 + 4P)) / 4 <= m <= (-1 + sqrt(1 + 2P)) / 2 ---(vi)
Solving equation (iii) for n, we have:
n = (P - 2m^2) / 2m ---(vii)
We iterate for m within the bounds given by the inequality (vi)
and check when the corresponding n given by equation (vii) is
an integer.
Despite generating all primitive triples, Euclid's formula does not
produce all triples - for example, (9, 12, 15) cannot be generated using
integer m and n. This can be remedied by inserting an additional
parameter k to the formula. The following will generate all Pythagorean
triples uniquely.
a = k(m^2 - n^2), b = 2kmn, c = k(m^2 + n^2), for k >= 1.
Thus, we iterate for integer values of P/k until P < 12,
lowest possible perimeter corresponding to the triple (3, 4, 5).
Yo
I don't know if you still need the answer or not but hopefully, this can help.
n = int(input())
ans = [(a, b, c) for a in range(1, n) for b in range(a, n) for c in range(b, n) if (a**2 + b**2 == c**2 and a + b + c == n)]
if ans:
print(ans[0][0], ans[0][1], ans[0][2])
else:
print("Impossible")
I have written a code to find Pythagorean triplets but it is not optimized
it took 5-6 minutes for the algorithm to find answer for big numbers...
my teacher said it should take less than 3 secs...
num = int(input())
def main(n):
for x in range(1, n):
for y in range(1, x):
for z in range(1, y):
if x + y + z == n:
if x * x == y * y + z * z or y * y == x * x + z * z or z * z == x * x + y * y:
a = f'{z} {y} {x}'
print(a)
return
else:
print('Impossible')
for example if you enter 12, you'll get 3,4,5
if you enter 30 , the answer will be 5,12,13
The sum of these three numbers must be equal to the number you entered.
can anyone please help me ?
Note the proof for the parametric representation of primitive pythagorean triples. In the proof, the author states:
We can use this proof to write an optimized algorithm:
def p(num):
a, b, c = 1, 1, 0
n = 0
while c < num:
for m in range(1, n):
a = 2 * m * n
b = n ** 2 - m ** 2
c = n ** 2 + m ** 2
if c >= num:
return "Impossible!"
elif a + b + c == num:
return b, a, c
n = n + 1
print(p(12)) # >>> (3, 4, 5)
print(p(30)) # >>> (5, 12, 13)
print(p(31)) # >>> Impossible!
You're doing a lot of repeated and unnecessary work. You know that A^2 + B^2 = C^2 and you know that C > B > A. It doesn't matter if you want to say C > A > B because any solution you find with that would be satisfied with C > B > A. For instance take 12 and solution 3, 4, 5. It doesn't actually matter if you say that A=3 and B=4 or A=4 and B=3. Knowing this we can adjust the loops of each for loop.
A can go from 1 to num, that's fine. Technically it can go to a bit less since you are adding another value to it that has to be at least 1 as well.
B then can go from A+1 to num since it needs to be greater than it.
So what about C? Well it doesnt' need to go from 1 since that's not possible. In fact we only care about A + B + C = num, so solve for C and you get C = num - A - B. That means you don't need to use a loop to find C since you can just solve for it. Knowing this you can do something like so:
In [142]: def find_triplet(num):
...: for a in range(1, num-1):
...: for b in range(a+1, num):
...: # A^2 + B^2 = C^2
...: # And A+B+C = N
...: c = num - a - b
...: if c > 0:
...: if a*a + b*b == c*c:
...: print(f'{a} {b} {c}')
...: else:
...: break
...:
In [143]: find_triplet(30)
5 12 13
So why check to see if C > 0 and break otherwise? Well, if you know C = num - A - B and you are incrementing B, then once B becomes too large, C is going to continue to get more and more negative. Because of that you can check if C > 0 and if it's not, break out of that inner loop to have A increment and B reset.
The approach you discussed takes O(n^3) complexity.
An efficient solution is to run two loops, where first loop runs from x = 1 to n/3, second loop runs from y = x+1 to n/2. In second loop, we check if (n – x – y) is equal to (x * x + y * y):
def pythagoreanTriplet(n):
# Considering triplets in
# sorted order. The value
# of first element in sorted
# triplet can be at-most n/3.
for x in range(1, int(n / 3) + 1):
# The value of second element
# must be less than equal to n/2
for y in range(x + 1,
int(n / 2) + 1):
z = n - x - y
if (x * x + y * y == z * z):
print(x, " ", y, " ", z)
return
print("Impossible")
# Driver Code
n = int(input())
pythagoreanTriplet(n)
PS: Time complexity = O(n^2)
I am trying to implement the function fast modular exponentiation(b, k, m) which computes:
b(2k) mod m using only around 2k modular multiplications.
I tried this method:
def FastModularExponentiation(b, k, m):
res = 1
b = b % m
while (k > 0):
if ((k & 1) == 1):
res = (res * b) % m
k = k >> 1
b = (b * b) % m
return res
but I am still stuck in same problem which is if I try b = 2, k = 1, m = 10, my code returns 22. However, the correct answer is:
2^(2^1) mod 10 = 2^2 mod 10 = 4
and I cannot find the reason why.
Update: I finally understood that you do not want regular modular exponentiation (i.e., b^k mod m), but b^(2^k) mod m (as you plainly stated).
Using the regular built-in Python function pow this would be:
def FastModularExponentiation(b, k, m):
return pow(b, pow(2, k), m)
Or, without using pow:
def FastModularExponentiation(b, k, m):
b %= m
for _ in range(k):
b = b ** 2 % m
return b
If you know r = phi(m) (Euler's totient function), you could reduce the exponent first: exp = pow(2, k, r) and then calculate pow(b, exp, m). Depending on the input values, this might speed things up.
(This was the original answer when I thought you wanted, b^k mod m)
This is what works for me:
def fast_mod_exp(b, exp, m):
res = 1
while exp > 1:
if exp & 1:
res = (res * b) % m
b = b ** 2 % m
exp >>= 1
return (b * res) % m
The only significant differences I spot is in the last line: return (b * res) % m and that my while loop terminates earlier: while exp > 1 (which should be the same thing you do - except it saves an unnecessary squaring operation).
Also note that the built-in function pow will do all that for free (if you supply a third argument):
pow(4, 13, 497)
# 445
def fast_exponentiation(k, x, q):
# make sure all variables are non-negative
assert (k >= 0 and x >= 0 and q >=1)
result = 1 # define a counter
while x:
if x % 2 == 1:
result = (result * k) % q
k = (k ^ 2) % q
x >> = 1 # bit shift operator, dividing x by 2 ** y thus x >> 2 ** 1 = x / 2
return result
Beginner here. I've spent most of the day working on the Karatsuba Algorithm just because I thought it would be fruitful. I've seen similar questions on here, but they are in other languages and seem strangely complex. The following is my code. The minute it hits the recursive call to ac, it just keeps on recursing. It's as if it never hits the base case. If anyone could be so kind as to offer some insight as to where things are going wrong, it would be greatly appreciated. For this code, you should assume I'm multiplying 2, base-10, four-digit numbers.
def karatsuba(x, y):
if len(str(x)) == 1 or len(str(y)) == 1:
return (x * y)
else:
n = (max(len(str(x)), len(str(y))))
a = x / 10**(n / 2)
b = x % 10**(n / 2)
c = y / 10**(n / 2)
d = y % 10**(n / 2)
ac = karatsuba(a, c)
ad = karatsuba(a, d)
bc = karatsuba(b, c)
bd = karatsuba(b, d)
product = (10**n*(ac) + 10**(n/2)*(ad + bc) + bd)
return product
print (karatsuba(1234, 5678))
Just fixing your code with integer divisions made it work correctly but here's a slight different version using 3 recursive calls (in base 10):
def karatsuba(x, y):
if x < 10 or y < 10:
return x * y
n = max(len(str(x)), len(str(y))) // 2
p = 10**n
a, b = divmod(x, p)
c, d = divmod(y, p)
ac = karatsuba(a, c)
bd = karatsuba(b, d)
abcd = karatsuba(a+b, c+d) - ac - bd
return (ac*p + abcd)*p + bd
But it is much faster operating in binary and using bit-twiddling:
def karatsuba(x, y):
if x < 16 or y < 16:
return x * y
n = max(x.bit_length(), y.bit_length()) // 2
mask = (1 << n) - 1
a, b = x >> n, x & mask
c, d = y >> n, y & mask
ac = karatsuba(a, c)
bd = karatsuba(b, d)
abcd = karatsuba(a+b, c+d) - ac - bd
return (((ac << n) + abcd) << n) + bd
Do you want integer division? In this case, you should use:
a = x // 10 ** (n / 2)
and
c = y // 10 ** (n / 2)
Otherwise, your program will be feeding through decimals to your function which I assume is not intended.
I'm also a beginner, feel free to correct me.
I am trying to find a root of a function by using the bisection method stating that :
if f(a)*f(b) < 0 then a root exists,
then you repeat with f(a)*f(c)<0 where c = (a+b)/2
but im not sure how to fix the code so it works properly.
This is my code but its not working properly
from scipy import *
from numpy import *
def rootmethod(f, a, b, tol):
x = a
fa = sign(eval(f))
x = b
fb = sign(eval(f))
c = a + b
iterations = 0
if fa == 0:
return a
if fb == 0:
return b
calls = 0
fx = 1
while fx != 0:
iterations = iterations + 1
c *= 0.5
x = a + c
fc = sign(eval(f))
calls = calls + 1
if fc*fa >= 0:
x = a
fx = sign(eval(f))
if fc == 0 or abs(sign(fc)) < eps:
fx = sign(eval(f))
return x, iterations, calls
print rootmethod("(x-1)**3 - 1", 1, 3, 10*e-15)
New edit.. but still doesnt work
if fa*fb < 0:
while fx != 0:
iterations = iterations + 1
c = (a + b)/2.0
x = c
fc = sign(eval(f))
calls = calls + 1
if fc*fa >= 0:
x = c
fx = sign(eval(f))
if fc == 0 or abs(sign(fc)) < tol:
fx = sign(eval(f))
return x, iterations, calls
Edit: Changed c=(a+b)*2 to c=(a+b)/2 in the description of the method.
Frankly your code was a bit of a mess. Here's some that works. Read the comments in the loop.
(BTW the solution to your given function is 2, not 3.75)
from scipy import *
from numpy import *
def rootmethod(f, a, b, tol):
x = a
fa = sign(eval(f))
x = b
fb = sign(eval(f))
c = a + b
iterations = 0
if fa == 0:
return a
if fb == 0:
return b
calls = 0
fx = 1
while 1:
x = (a + b)/2
fx = eval(f)
if abs(fx) < tol:
return x
# Switch to new points.
# We have to replace either a or b, whichever one will
# provide us with a negative
old = b # backup variable
b = (a + b)/2.0
x = a
fa = eval(f)
x = b
fb = eval(f)
# If we replace a when we should have replaced b, replace a instead
if fa*fb > 0:
b = old
a = (a + b)/2.0
print rootmethod("(x-1)**3 - 1", 1, 3, 0.01)
I believe your loop should be something like this (in pseudocode, and leaving out some checking):
before loop:
a is lower bound
b is upper bound
Establish that f(a) * f(b) is < 0
while True:
c = (a+b)/2
if f(c) is close enough to 0:
return c
if f(a) * f(c) > 0:
a = c
else
b = c
In other words, if the midpoint isn't the answer, then make it one of the new endpoints depending on its sign.
I think your one problem is with:
x = a + c
Since c = (a + b)*.5, you don't need to add in a here...
Update
You don't seem to check if fa * fb < 0 to start, and I also don't see where you're narrowing your bounds: you should either reassign a or b to c in your loop and then recalculate c.
Code It's been a while since I played with python last, so take it with a grain of salt ^_^
x = a
fa = sign(eval(f))
x = b
fb = sign(eval(f))
iterations = 0
if fa == 0:
return a
if fb == 0:
return b
calls = 0
fx = 1
while fa != fb:
iterations += 1
c = (a + b)/2.0
x = c
fc = eval(f)
calls += 1
if fc == 0 or abs(fc) < tol:
#fx = fc not needed since we return and don't use fx
return x, iterations, calls
fc = sign(fc)
if fc != fa:
b = c
fb = fc
else
a = c
fa = fc
#error because no zero is expected to be found
Please note that the code has a simple deficiency caused by round-off errors
a=0.015707963267948963
b=0.015707963267948967
c=(a+b)*.5
c is becoming b again (check it out!).
You can end up in infinite loop
in case of very small tolerance like 1e-16.
def FindRoot( fun, a, b, tol = 1e-16 ):
a = float(a)
b = float(b)
assert(sign(fun(a)) != sign(fun(b)))
c = (a+b)/2
while math.fabs(fun( c )) > tol:
if a == c or b == c:
break
if sign(fun(c)) == sign(fun(b)):
b = c
else:
a = c
c = (a+b)/2
return c
Now, to call the eval over and over again is not very efficient.
Here is what you can do instead
expr = "(x-1.0)**3.0 - 1.0"
fn = eval( "lambda x: " + expr )
print FindRoot( fn, 1, 3 )
Or you can put the eval and lambda definition inside the FindRoot.
Was it helpful?
Reson