Speeding up perfect swap calculation - avoiding loops - python

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

Related

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

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.

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)

How to obtain the result of n(n-1)(n-2) / 6

In my Python book, the question asks to prove the value of x after running the following code:
x = 0
for i in range(n):
for j in range(i+1, n):
for k in range(j+1, n):
x += 1
What I could see is that:
i = 0; j=1; k=2: from 2 to n, x+=1, (n-2) times 1
i = 1; j=2; k=3: from 3 to n, x+=1, (n-3) times 1
...
i=n-3; j=n-2; k=n-1: from n-1 to n, x+=1, just 1
i=n-2; j=n-1; k=n doesn't add 1
So it seems that the x is the sum of series of (n-2) + (n-3) + ... + 1?
I am not sure how to get to the answer of n(n-1)(n-2)/6.
One way to view this is that you have n values and three nested loops which are constructed to have non-overlapping ranges. Thus the number of iterations possible is equal to the number of ways to choose three unique values from n items, or n choose 3 = n!/(3!(n-3)!) = n(n-1)(n-2)/3*2*1 = n(n-1)(n-2)/6.
Just write the for loops as a sigma: S = sum_{i=1}^n sum_{j=i+1}^n sum_{k = j + 1}^n (1).
Try to expand the sum from inner to outer:
S = sum_{i=1}^n sum_{j=i+1}^n (n - j) = sum_{i=1}^n n(n-i) - ((i+1) + (i+2) + ... + n) = sum_{i=1}^n n(n-i) - ( 1+2+...+n - (1+2+...+i)) = sum_{i=1}^n n(n-i) -(n(n+1)/2 - i(i+1)/2) = sum_{i=1}^n n(n+1)/2 + i(i+1)/2 - n*i = n^2(n+1)/2 + sum_{i=1}^n (i^2/2 + i/2 - n*i).
If open this sum and simplify it (it is straightforward) you will get S = n(n-1)(n-2)/6.

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).

Any better algorithm possible here?

I am trying to solve this problem in Python. Noting that only the first kiss requires the alternation, any kiss that is not a part of the chain due to the first kiss can very well have a hug on the 2nd next person, this is the code I have come up with. This is just a simple mathematical calculation, no looping, no iteration, nothing. But still I am getting a timed-out message. Any means to optimize it?
import psyco
psyco.full()
testcase = int(raw_input())
for i in xrange(0,testcase):
n = int(raw_input())
if n%2:
m = n/2;
ans = 2 + 4*(2**m-1);
ans = ans%1000000007;
print ans
else:
m = n/2 - 1
ans = 2 + 2**(n/2) + 4*(2**m-1);
ans = ans%1000000007
print ans
You're computing powers with very large exponents, which is extremely slow if the results are not reduced in process. For example, a naive computation of 10**10000000 % 11 requires creating a 10000000-digit number and taking modulo 11. A better way is modular exponentiation where you reduce modulo 11 after each multiplication and the integer never gets larger.
Python provides built-in modular exponentiation. Use pow(a,b,c) to compute (a**b) % c.
This is under assumption that your algorithm is correct, which I did not verify.
The answer to this is a pretty simple recursion. F(1) = 2 and for F(n) we have two choices:
n = H, then the number of ways to kiss the remaining guests is simply F(n-1)
n = K, then the number of ways to kiss the remaining guests is 2 ** k where k is the number of remaining guests that the princess is not forced to kiss. Since she has to kiss every second remaining guest, k = ceil((n - 1) / 2)
Putting them together, we get F(n) = F(n - 1) + 2 ** ceil((n - 1) / 2)
My attempt, including taking everything mod 1000000007:
from math import ceil
def F(n):
m = 1000000007
a = 2
for i in range(2, n+1):
a = (a + pow(2, int(ceil((i - 1.0) / 2)), m)) % m
return a
EDIT: Updated (much faster and more unreadable! F(1e9) takes about 3 minutes):
def F(n):
m = 1000000007
a = 2
z = 1
for i in xrange(2, n, 2):
z = (z * 2) % m
a = (a + z + z) % m
if (n & 1 == 0):
z = (z * 2) % m
a = (a + z) % m
return a
EDIT 2: After further thought, I realised the above is actually just:
F(n) = (1 + 1) + (2 + 2) + (4 + 4) + ... + (2 ** n/2 + 2 ** n/2)
= 2 * (1 + 2 + 4 + ... + 2 ** n/2)
= 2 * (2 ** (n/2 + 1) - 1)
= 2 ** (n/2 + 2) - 2
But if n is even, the last 2 ** n/2 only occurs once, so we have:
def F(n):
m = 1000000007
z = pow(2, n/2, m)
if (n % 2 == 0):
return (z * 3 - 2) % m
else:
return (z * 4 - 2) % m
Which runs much faster! (Limited by the speed of pow(x, y, z), which I think is O(lg n)?)
And just because, here is the one-liner:
def F(n):
return (pow(2, n/2, 1000000007) * (3 + n % 2) - 2) % 1000000007
Results:
1 => 2
2 => 4
3 => 6
4 => 10
5 => 14
6 => 22
7 => 30
8 => 46
9 => 62
10 => 94
1e6 => 902893650
1e7 => 502879941
1e8 => 251151906
1e9 => 375000001

Categories