How i **2 different from i * i in python while calculating? - python

I was trying to solve Leetcode#279.Perfect-Squares
When I tried i ** 2 in loops, I got Time Limit Exceed. But once I change it to i * i, the code was accepted, that means i * i is faster than i ** 2 in python
What principles in python3 caused this difference?
Code and result for reference:
Use j * j, AC, beats 23%
class Solution:
def numSquares(self, n: int):
if n < 2:
return n
dp = [n] * (n + 1)
dp[0] = 0
dp[1] = 1
for i in range(2, n + 1):
j = 1
while j * j <= i:
dp[i] = min(dp[i], dp[i - j * j] + 1)
j += 1
return dp[-1]
If change all j * j to j ** 2, TLE.

Related

Speeding up perfect swap calculation - avoiding loops

import sys
t=(int(sys.stdin.readline()))
for i in range(0,t):
n=int(sys.stdin.readline())
c=0
s=n*(n+1)/2
if s%2!=0:
print(0)
else:
c=0
i=-1
a=[i for i in range(1,n+1)]
h=s//2
m=0
s1=0
for i in range(n-1,-1,-1):
s1+=a[i]
c+=1
if s1==h:
m=1
break
if s1>h:
break
if m==1:
s1=((c+1)*(2+((c-1)-1)))//2+((n-c-1)*(2+((n-c-1)-1)))//2
print(s1)
else:
print(c)
I am new to python , How can i write this code with using for loop? i don't want to use for loop because i get TLE error. Thanks in advance
Here is the question :
N. Consider the sequence sequence=(1,2,…,N). You should choose two elements of this sequence and swap them.
A swap is perfect if there is an integer o (1≤o<N) such that the sum of the first M elements of the resulting sequence is equal to the sum of its last N−o elements. Find the number of perfect swaps.
i got interested in the problem and found this so far:
a slow version that creates list and really does swap elements is this:
from itertools import combinations
def slow(N):
found = 0
for i, j in combinations(range(N), 2):
lst = list(range(1, N + 1))
lst[i], lst[j] = lst[j], lst[i]
for m in range(1, N):
a = m * (m + 1) // 2
b = (N - m) * (N + m + 1) // 2
if i < m <= j:
a = a - i + j
b = b - j + i
assert a == sum(lst[:m])
assert b == sum(lst[m:])
if sum(lst[:m]) == sum(lst[m:]):
found += 1
if i < m <= j:
assert 2 * m * (m + 1) + 4 * j == N * (N + 1) + 4 * i
else:
assert 2 * m * (m + 1) == N * (N + 1)
else:
if i < m <= j:
assert 2 * m * (m + 1) + 4 * j != N * (N + 1) + 4 * i
else:
assert 2 * m * (m + 1) != N * (N + 1)
return found
as you see i found criteria the indices have to fulfill in order for the sum to be correct:
if i < m <= j:
assert 2 * m * (m + 1) + 4 * j == N * (N + 1) + 4 * i
else:
assert 2 * m * (m + 1) == N * (N + 1)
i also found the direct formula to calculate the sum up to m and the one starting from m:
a = m * (m + 1) // 2
b = (N - m) * (N + m + 1) // 2
if i < m <= j:
a = a - i + j
b = b - j + i
all of that can can be calculated using some basic mathematics.
starting from that you can do some more maths and see that there are 2 cases to consider:
there is an m such that the sum of the original list [1, 2, 3, ..., m, m+1, ..., N] up to m equals the sum of the rest of the list (e.g. N = 20; m = 14). two cases again:
all the swaps that do not cross the m boundary are valid (there are comb(m, 2) + comb((N - m), 2)) of them.
when you split at m-1 you will find more swaps; this time you have to swap accross the m-1 boundary.
the m in that case is calculated from
m = - 1 + sqrt(1 + 2 * N * (N + 1)) / 2
the calculation for m in the first case is not an integer (i.e. 1 + 2 * N * (N + 1) is not a perfect square). the m to consider is then then the floor of the result of the formula above (i use int instead of math.floor). two cases again for the difference of the sum of the two splits:
the difference is even: there are more swaps that need to go over the m boundary.
the difference is odd: no additional swaps (swapping will always result in an even difference)
this is the code:
from math import sqrt, comb
def fast(N):
found = 0
arg = (1 + 2 * N * (N + 1))
sq = round(sqrt(arg))
if sq ** 2 == arg and sq & 1:
m = (-1 + sq) // 2
found += comb(m, 2) + comb((N - m), 2)
m -= 1
found += N - m - 1
else:
m = int((-1 + sqrt(arg)) // 2)
diff = ((m + 1 + N) * (N - m) - m * (m + 1)) // 2
if diff & 1 == 0:
found += N - m
return found

Pythagorean triple with python

I want to get a number 'n' and produce Pythagorean triple that total of them is equal with 'n'.
for example for n=12 my output is 3, 4, 5 (12 = 3 + 4 + 5).
I write below code but it take a lot of time for big numbers. please help me to improve it.
a = int(input())
done = False
for i in range(int(a/4)+1,2,-1):
if done:
break
for j in range(i+1,int(a/2)+1):
k = a-(i+j)
if k <= j:
break
if i**2 + j**2 == k**2:
print(i,j,k)
done = True
break
if done == False:
print('Impossible')
This code may help you
limits = int(input())
c, m = 0, 2
# Limiting c would limit
# all a, b and c
while c < limits :
# Now loop on n from 1 to m-1
for n in range(1, m) :
a = m * m - n * n
b = 2 * m * n
c = m * m + n * n
# if c is greater than
# limit then break it
if c > limits :
break
if a+b+c == limits:
print(a, b, c)
m = m + 1
>> 12
>> 3 4 5
I've used the joblib module to parallelize your code, though I haven't tested if there is a speedup for very large n; let me know:
from joblib import Parallel, delayed
done = False
def triple(a):
global done
for i in range(int(a/4)+1,2,-1):
if done:
break
for j in range(i+1,int(a/2)+1):
k = a-(i+j)
if k <= j:
break
if i**2 + j**2 == k**2:
print(i,j,k)
done = True
break
if done == False:
print('Impossible')
if __name__ == '__main__':
a = int(input("n:"))
Parallel(n_jobs=-1, backend="threading")(map(delayed(triple), [a]))
To generate a Pythagorean triplet of a given sum, you can run two loops, where the first loop runs from i = 1 to n/3, the second loop runs from j = i+1 to n/2. In second loop, we check if (n – i – j) is equal to i * i + j * j.
n = int(input()
for i in range(1, int(n / 3) + 1):
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)

why use True is slower than use 1 in Python3

I've read this question: Why is if True slower than if 1?, but i'm using Python3 now. I am writing leetcode 204 and someone said that using one is faster than using two.
My code:
import timeit
count = 1000
def countPrimes(n=100000):
if n < 3:
return 0
primes = [True] * n
primes[0], primes[1] = False, False
for i in range(2, int(n ** 0.5) + 1):
if primes[i]:
for j in range(i * i, n, i):
primes[j] = False
return sum(primes)
def countPrimes2(n=100000):
if n < 3:
return 0
primes = [1] * n
primes[0], primes[1] = 0, 0
for i in range(2, int(n ** 0.5) + 1):
if primes[i]:
for j in range(i * i, n, i):
primes[j] = 0
return sum(primes)
print('use False,True ', timeit.timeit(countPrimes, number=count))
print('use 0,1 ', timeit.timeit(countPrimes2, number=count))
The result is:
-> % python3 test.py
use False,True 10.634566191001795
use 0,1 9.187052419991232
Can anyone tell me why?
ok, as furas said, it's the sum cost much time:
import timeit
count = 1000
def countPrimes(n=100000):
primes = [True] * n
return sum(primes)
def countPrimes2(n=100000):
primes = [1] * n
return sum(primes)
print('use False,True ', timeit.timeit(countPrimes, number=count))
print('use 0,1 ', timeit.timeit(countPrimes2, number=count))
result is:
-> % python3 test.py
use False,True 2.4546820300165564
use 0,1 1.0242620470235124
without sum:
import timeit
count = 1000
def countPrimes(n=100000):
if n < 3:
return 0
primes = [True] * n
primes[0], primes[1] = False, False
for i in range(2, int(n ** 0.5) + 1):
if primes[i]:
for j in range(i * i, n, i):
primes[j] = False
def countPrimes2(n=100000):
if n < 3:
return 0
primes = [1] * n
primes[0], primes[1] = 0, 0
for i in range(2, int(n ** 0.5) + 1):
if primes[i]:
for j in range(i * i, n, i):
primes[j] = 0
print('use False,True ', timeit.timeit(countPrimes, number=count))
print('use 0,1 ', timeit.timeit(countPrimes2, number=count))
result is:
-> % python3 test.py
use False,True 8.47771276300773
use 0,1 8.44074950099457
time is almost the same

Redundant lines in 0/1 Matrix output

I am trying to create a script that can allows me to output all the different combinations possible for different project optimization choices. In short, there are 6 projets (A B C D E F) that each have 2, 3 or 6 possible choices of optimization, that are mutually exclusive (you can't choose F4 and F5 at the same time for example).
import numpy as np
A = range(1, 3)
B = range(1, 3)
C = range(1, 7)
D= range(1,3)
E=range(1,3)
F=range(1,4)
length = len(A) + len(B) + len(C) + len(D) + len(E) + len(F)
nb_projet = len(A) * len(B) * len(C) * len(D) * len(E) * len(F)
result = np.zeros((length, nb_projet))
for k in range(len(A)):
for i in range(len(A)):
for j in range(nb_projet):
result[i, j] = (i+j % len(A)) == k
for k in range(len(B)):
for i in range(len(B)):
for j in range(nb_projet):
result[i + len(A), j] = (i+j % len(B)) == k
for k in range(len(C)):
for i in range(len(C)):
for j in range(nb_projet):
result[i + len(A)+len(B), j] = (i+j % len(C)) == k
for k in range(len(D)):
for i in range(len(D)):
for j in range(nb_projet):
result[i + len(A)+len(B)+len (C), j] = (i+j % len(D)) == k
for k in range(len(E)):
for i in range(len(E)):
for j in range(nb_projet):
result[i + len(A)+len(B)+len (C)+len(D), j] = (i+j % len(E)) == k
for k in range(len(F)):
for i in range(len(F)):
for j in range(nb_projet):
result[i + len(A)+len(B)+len (C)+len(D)+len(E), j] = (i+j % len(F)) == 0
print (result.T)
np.savetxt("ResultsS2.txt", result, delimiter=" ")
Basically the code is supposed to add a 1 if the optimization is chosen. At the moment it only generates 6 differents scenarios and not the 250+ that are possible.
Does anyone have an idea on how to fix this ?
Thank yu a lot !
This is just a bunch of concatenated one-hot arrays, so utilizing the second answer here and meshgrid to create the full factorial, you can just do something like this:
projects = [2,2,6,2,2,3] #[A.size, B.size, C.size . . .]
m = np.meshgrid(*[np.arange(i) for i in projects])
oneHots = [np.eye(projects[i])[m[i].flat] for i in range(len(projects))]
out = np.hstack(oneHots).T
out.shape
>(17, 288)
You can use something like this. Not the smartest, but if the arrays are not too long, it would work perfectly.
import numpy as np
A = range(0, 2)
B = range(0, 2)
C = range(0, 6)
length = len(A) + len(B) + len(C)
nb_projet = len(A) * len(B) * len(C)
result = np.zeros((length, nb_projet))
selectedList = []
count = 0
for i in A:
for j in B:
for k in C:
result[(i,count)]= 1
result[(len(A)+j,count)]=1
result[(len(A)+len(B)+k, count)] = 1
count+=1
Note, that I had changed the ranges to fit better.

How can I improve my algorithm runtime? cpmoptimithe not to propose

I need to find all the combinations flowers. Number of flowers only odd. Purchase amount not greater than the predetermined.
def bouquets(narcissus_price, tulip_price, rose_price, summ):
count_combinations = 0
for n in xrange(int(summ / narcissus_price) + 1):
for t in xrange(int(summ / tulip_price) + 1):
if n * narcissus_price + t * tulip_price > summ:
break
for r in xrange([1,0][(n + t) % 2], int(summ / rose_price) + 1, 2):
if n * narcissus_price + t * tulip_price + r * rose_price > summ:
break
elif (n + t + r) & 1:
count_combinations += 1
return count_combinations
print bouquets(200, 300, 400, 100000) == 3524556 # large run-time
Reduce the iteration range for tulips - rather than iterating to summ // tulip_price you can stop at (summ - n * narcissus_price) // tulip_price
You can count the number of possible values for r without enumerating them
Example:
def bouquets(n_price, t_price, r_price, total_price):
"""
Count how many n, t, r (integers >= 0) exist
such that
n * n_price + t * t_price + r * r_price <= total_price
and
n + t + r is odd
"""
count = 0
max_n = total_price // n_price
for n in xrange(max_n + 1):
rem_n = total_price - n * n_price
max_t = rem_n // t_price
for t in xrange(max_t + 1):
rem_t = rem_n - t * t_price
max_r = rem_t // r_price
min_r = (n + t + 1) % 2
count += (max_r - min_r) // 2 + 1
return count
On the given test input, this reduces the runtime from 2.33s to 67.2ms (about 35 times faster).

Categories