Can anyone reduce time complexity of this code - python

You are given three integers A, B, and C. You are allowed to perform the following operation any number of times (possibly zero).
• Choose any integer X such that X ≤ max (A,B, C), and replace A with
A^X, B with B^X, and C with C^X.
Here denote Bitwise XOR operation.
Find the maximum possible value of A+B+C.
A=2
B=2
C=2
def maxSum(a,b,c):
list=[]
l=[a,b,c]
l.sort()
if a==b==c:
for x in range(int(a/2),l[-1]):
new=((a^x)+(b^x)+(c^x))
list.append(new)
return list[-1]
else:
for x in range(l[1],l[-1]):
new=((a^x)+(b^x)+(c^x))
list.append(new)
return list[-1]
maximum=maxSum(A,B,C)
print(maximum)
How to make the code run faster?
I tried using for loop but the runtime was so much. I want to know how to reduce runtime. What are the modifications needed.

Try this:
def max_sum(a, b, c):
for j in range(int.bit_length(max(a, b, c))):
x = 2**j if sum((n & 2**j) >> j for n in (a, b, c)) < 2 else 0
a = a ^ x
b = b ^ x
c = c ^ x
return a + b + c
So here you perform a number of operations equal to the number of bits of the largest number. x is either a power of 2 or 0.
Example:
>>> max_sum(8, 3, 5)
30

Related

Error for trapezoidal method increases with N if integral equals 0 [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed last month.
I've written a simple implementation of the trapezoidal method to find the integral of sine:
def trapezoidal_method(a: float, b: float, n: int) -> float:
length = (b - a)/n
integral = 0
start = a
integral += math.sin(a)/2
for _ in range(1, n):
integral += math.sin(start + length)
start += length
integral += math.sin(b)/2
return integral * length
It converges as expected for most situations...
but it goes crazy when the result should be 0 (like integrating from -1 to 1):
How do I fix this? Tried explicitly casting n to float and tried using the decimal library, didn't change anything
That's (mainly) due to floating number precision. In the case of functions as sine, which are transcendental by nature, only an approximation of it is possible (or depends on its implementation).
By adding a (very quick!) a print of the x and y values at each term of the sequence you will see the odd symmetry is not respected... or at least with a small error. So, f(x) = -f(-x) + error.
import math
def trapezoidal_method(func, a: float, b: float, n: int) -> float:
length = (b - a)/n
integral = 0
start = a
integral += func(a)/2
for _ in range(1, n):
integral += func(start + length)
start += length
integral += func(b)/2
# evaluation for each term of the sequence
print(0, f'x={a} y={func(a)}')
x = a
for i in range(1, n):
x += length
y = func(x)
print(i, f'{x=} {y=}')
print(n, f'x={b} y={func(b)}')
return integral * length
A test with sin
a, b, n = -1, 1, 7
func = math.sin
tm = trapezoidal_method(func, a, b, n)
Output
0 x=-1 y=-0.8414709848078965
1 x=-0.7142857142857143 y=-0.6550778971785186
2 x=-0.4285714285714286 y=-0.41557185499305205 # <-
3 x=-0.1428571428571429 y=-0.1423717297922637
4 x= 0.1428571428571428 y=0.1423717297922636
5 x= 0.4285714285714285 y=0.41557185499305194 # <-
6 x= 0.7142857142857142 y=0.6550778971785185
8 x= 1 y=0.8414709848078965
-1.586032892321652e-16
Notice that also the x-values maybe slightly different!
By choosing suitable limits of integration and amount of strips then the in some cases the integral maybe 0. Here an example with the diagonal function
a, b, n = -1, 1, 6
func = lambda x: x
tm = trapezoidal_method(func, a, b, n)
Output
0 x=-3.0 y=-3.0
1 x=-2.0 y=-2.0
2 x=-1.0 y=-1.0
3 x=0.0 y=0.0
4 x=1.0 y=1.0
5 x=2.0 y=2.0
7 x=3.0 y=3.0
0.0

Write a function that, given natural numbers n, m, determines the smallest natural number k such that n^k >= m, in time O(log k)

I can do it in only O(k) time can someone be that kind to help me. I can not use build in functions.
def potnr(a, b):
rez = 1
while b>0:
if b%2:
rez = rez * a
b = b // 2
a = a * a
return rez
def liczba(n, m):
k = 1
while potnr(n, k) < m:
k += 1
return k
print(liczba(2, 16))
I can do it in only O(k) time can someone be that kind to help me
n^k >= m if and only if k >= log m base n
Since log m base n = log m / log n, this is as simple as:
from math import log, ceil
def smallest_k(n, m):
return ceil(log(m)/log(n))
This runs in O(1) time.
This one should work (I just fixed the value of k returned, for there was no guarantee it was the smallest value with the previous return):
import math
def min_power(n,m):
b=1
while n**b < m:
b *= 2
a = b/2
while b-a > 1:
c = (a+b)/2
if n**c < m:
a = c
else:
b = c
k = math.ceil(a)
return k if (n**k >= m) else k+1
min_power(35,10**250)
# Out[23]: 162
First determine any natural number k for which n ^ k >= m. Then refine your estimate to find the smallest such k.
It's easiest to find the initial estimate for k as a power of 2. Have a temporary value which holds n ^ k. Start from k = 1, repeatedly multiply k by 2, and square your temporary variable, until your k is sufficiently big.
Your real k will be greater than half the estimate you found. Numbers in that range have log2(k) bits. Check each bit, starting from the most significant one. For each such bit, calculate n ^ k for two values of k: with that bit equal to 0 and 1. Compare with m - this will tell you the value of that bit. Proceed to lower-significant bits, until you get to bit 0 (least significant bit).
I am not sure you are allowed to assume that calculating n ^ k has O(1) complexity. If not, you have to store intermediate results for all n ^ k calculations at first stage, or alternatively, use sqrt to calculate lesser powers of n.

How to check if abc == sqrt(a^b^c) very fast (preferably Python)?

Let a,b,c be the first digits of a number (e.g. 523 has a=5, b=2, c=3). I am trying to check if abc == sqrt(a^b^c) for many values of a,b,c. (Note: abc = 523 stands for the number itself.)
I have tried this with Python, but for a>7 it already took a significant amount of time to check just one digit combination. I have tried rewriting the equality as multiple logs, like log_c[log_b[log_a[ (abc)^2 ]]] == 1, however, I encountered Math Domain Errors.
Is there a fast / better way to check this equality (preferably in Python)?
Note: Three digits are an example for StackOverflow. The goal is to test much higher powers with seven to ten digits (or more).
Here is the very basic piece of code I have used so far:
for a in range(1,10):
for b in range(1,10):
for c in range(1,10):
N = a*10**2 + b*10 + c
X = a**(b**c)
if N == X:
print a,b,c
The problem is that you are uselessly calculating very large integers, which can take much time as Python has unlimited size for them.
You should limit the values of c you test.
If your largest possible number is 1000, you want a**b**c < 1000**2, so b**c < log(1000**2, a) = 2*log(1000, a)), so c < log(2*log(1000, a), b)
Note that you should exclude a = 1, as any power of it is 1, and b = 1, as b^c would then be 1, and the whole expression is just a.
To test if the square root of a^b^c is abc, it's better to test if a^b^c is equal to the square of abc, in order to avoid using floats.
So, the code, that (as expected) doesn't find any solution under 1000, but runs very fast:
from math import log
for a in range(2,10):
for b in range(2,10):
for c in range(1,int(log(2*log(1000, a), b))):
N2 = (a*100 + b*10 + c)**2
X = a**(b**c)
if N2 == X:
print(a,b,c)
You are looking for numbers whose square root is equal to a three-digit integer. That means your X has to have at most 6 digits, or more precisely log10(X) < 6. Once your a gets larger, the potential solutions you're generating are much larger than that, so we can eliminate large swathes of them without needing to check them (or needing to calculate a ** b ** c, which can get very large: 9 ** 9 ** 9 has 369_693_100 DIGITS!).
log10(X) < 6 gives us log10(a ** b ** c) < 6 which is the same as b ** c * log10(a) < 6. Bringing it to the other side: log10(a) < 6 / b ** c, and then a < 10 ** (6 / b ** c). That means I know I don't need to check for any a that exceeds that. Correcting for an off-by-one error gives the solution:
for b in range(1, 10):
for c in range(1, 10):
t = b ** c
for a in range(1, 1 + min(9, int(10 ** (6 / t)))):
N = a * 100 + b * 10 + c
X = a ** t
if N * N == X:
print(a, b, c)
Running this shows that there aren't any valid solutions to your equation, sadly!
a**(b**c) will grow quite fast and most of the time it will far exceed three digit number. Most of the calculations you are doing will be useless. To optimize your solution do the following:
Iterate over all 3 digit numbers
For each of these numbers square it and is a power of the first digit of the number
For those that are, check if this power is in turn a power of the second digit
And last check if this power is the third digit

Complement of XOR

What is the most efficient algorithm for finding ~A XOR B? (Note that ~ is the complement function, done by reversing each 1 bit into 0 and each 0 into 1 bit, and XOR is the exclusive or function)
For example, ~4 XOR 6 = ~010 = 101 = 5 and ~6 XOR 9 = ~1111 = 0
Here's an answer that takes into account the number of bits needed to store your integers:
def xnor(a, b):
length = max(a.bit_length(), b.bit_length())
return (~a ^ b) & ((1 << length) - 1)
I can't think of a situation where this is better than just ~a ^ b however. And it almost certainly makes no sense for negative numbers.
The only problem here is that ~ returns a negative number for a positive input, and you want a positive result limited to the significant bits represented in the inputs.
Here's a function that can generate a mask of bits that are needed in the result:
def mask(n):
n = abs(n)
shift = 1
while n & (n + 1) != 0:
n |= n >> shift
shift *= 2
return n
And here's how to use it:
print (~a ^ b) & mask(a | b)
You can simply use ==.
A XNOR B is same as == operator because:
A B NXOR
F F T
F T F
T F F
T T T

What is the best way to generate Pythagorean triples?

I have tried with that simple code when you just check all the combinations for a and b and then check if square root of c is an integer, but that code is really slow, then I have tried with Euclid's formula
a = d*(n^2 - m^2)
b = 2*n*m*d
c = d*(n^2 + m^2)
and I have written a code where you first find n with
trunc(sqrt(max_value))
//this is in pascal
and then you check every combination of 0 < m < n but I get duplicate results, like if n is 7, m is 5 and d is 1, and n is 6, m is 1 and d is 2 . In both cases you get 24, 70 and 74. So what is a good fast way to calculate the number of Pythagorean triples, I can't seem to find a way, also if I add all results to an array, and then check the array for duplicates, it just takes too much time... If anyone can help me with the code it can be pascal, c or python, I can understand all...
The Wikipedia page on Pythagorean triples gives us a hint:
The triple generated by Euclid's formula is primitive if and only if m and n are coprime and m − n is odd. If both m and n are odd, then a, b, and c will be even, and so the triple will not be primitive; however, dividing a, b, and c by 2 will yield a primitive triple if m and n are coprime
If you restrict m and n to coprime numbers and force m - n to be odd you will uiniquely generate all the primitive pythagorean triples. From this point on, you should be able to multiply these unique triples by factors of d to uniquely generate all triples.
In your example, allowing n=7 and m=5 was the problem, because their difference was even and the triple they generated was not primitive (you could divide all sides by 2 to get a smaller triple)
I was curious so I decided to try this. I found that this algorithm was pretty easy to implement in Python and works pretty fast:
import math
def pythagorean_triples(n):
a, b, c = 1, 3, 0
while c < n:
a_ = (a * b) + a
c = math.sqrt(a_**2 + b**2)
if c == int(c):
yield b, a_, int(c)
a += 1
b += 2
if __name__ == '__main__':
import sys
for pt in pythagorean_triples(int(sys.argv[1])):
print(pt)
Try it by copying that script into pythagorean_triples.py and running python3 pythagorean_triples.py n where n is the maximum c you want it to generate. (You can use later Python2 if you like as well.)

Categories

Resources