Can someone explain this recursive for me? - python

I get this code from leetcode.
class Solution(object):
def myPow(self, x, n):
if n == 0:
return 1
if n == -1:
return 1 / x
return self.myPow(x * x, n / 2) * ([1, x][n % 2])
This code is used to implement poe(x, n), which means x**n in Python.
I want to know why it can implement pow(x, n).
It looks doesn't make sense...
I understand
if n == 0:
and
if n == -1:
But the core code:
self.myPow(x * x, n / 2) * ([1, x][n % 2])
is really hard to understand.
BTW, this code only works on Python 2.7. If you want to test on Python 3, you should change
myPow(x*x, n / 2) * ([1, x][n % 2])
to
myPow(x*x, n // 2) * ([1, x][n % 2])

The recursive function is to compute power (most probably integer, non negative or -1, power) of a number, as you might have expected (something like x = 2.2 and n = 9).
(And this seems to be written for Python 2.x (due to the n/2 having expected result of integer instead of n//2))
The initial returns are very straight-forward math.
if n == 0:
return 1
if n == -1:
return 1 / x
When the power is 0, then you return 1 and then the power is -1, you return 1/x.
Now the next line consists of two elements:
self.myPow(x * x, n/2)
and
[1, x][n%2]
The first one self.myPow(x * x, n/2) simply means you want to make higher power (not 0 or -1) into half of it by squaring the powered number x
(most probably to speed up the calculation by reducing the number of multiplication needed - imagine if you have case to compute 2^58. By multiplication, you have to multiply the number 58 times. But if you divide it into two every time and solve it recursively, you end up will smaller number of operations).
Example:
x^8 = (x^2)^4 = y^4 #thus you reduce the number of operation you need to perform
Here, you pass x^2 as your next argument in the recursive (that is y) and do it recursively till the power is 0 or -1.
And the next one is you get the modulo of two of the divided power. This is to make up the case for odd case (that is, when the power n is odd).
[1,x][n%2] #is 1 when n is even, is x when n is odd
If n is odd, then by doing n/2, you lose one x in the process. Thus you have to make up by multiplying the self.myPow(x * x, n / 2) with that x. But if your n is not odd (even), you do not lose one x, thus you do not need to multiply the result by x but by 1.
Illustratively:
x^9 = (x^2)^4 * x #take a look the x here
but
x^8 = (x^2)^4 * 1 #take a look the 1 here
Thus, this:
[1, x][n % 2]
is to multiply the previous recursion by either 1 (for even n case) or x (for odd n case) and is equivalent to ternary expression:
1 if n % 2 == 0 else x

This is divide and conquer technique. The implementation above is a fast way of computing exponentiation. At each call, half of the multiplications are eliminated.
Assuming that n is even, x^n can be written as below (If n is odd, it requires one extra multiplication)
x^n = (x^2)^(n/2)
or
x^n = (x^n/2)^2
The function shown above implements the 1st version. It's easy to implement the 2nd one also (I removed recursion base cases below)
r = self.myPow(x,n/2)
return r * r * ([1, x][n % 2])

The right answer might be below
class Solution:
def myPow(self, x: float, n: int) -> float:
if n == 0:
return 1
if n > 0:
return self.myPow(x * x, int(n / 2)) * ([1, x][n % 2])
else:
return self.myPow(x * x, int(n / 2)) * ([1, 1/x][n % 2])

Related

Let n be a square number. Using Python, how we can efficiently calculate natural numbers y up to a limit l such that n+y^2 is again a square number?

Using Python, I would like to implement a function that takes a natural number n as input and outputs a list of natural numbers [y1, y2, y3, ...] such that n + y1*y1 and n + y2*y2 and n + y3*y3 and so forth is again a square.
What I tried so far is to obtain one y-value using the following function:
def find_square(n:int) -> tuple[int, int]:
if n%2 == 1:
y = (n-1)//2
x = n+y*y
return (y,x)
return None
It works fine, eg. find_square(13689) gives me a correct solution y=6844. It would be great to have an algorithm that yields all possible y-values such as y=44 or y=156.
Simplest slow approach is of course for given N just to iterate all possible Y and check if N + Y^2 is square.
But there is a much faster approach using integer Factorization technique:
Lets notice that to solve equation N + Y^2 = X^2, that is to find all integer pairs (X, Y) for given fixed integer N, we can rewrite this equation to N = X^2 - Y^2 = (X + Y) * (X - Y) which follows from famous school formula of difference of squares.
Now lets rename two factors as A, B i.e. N = (X + Y) * (X - Y) = A * B, which means that X = (A + B) / 2 and Y = (A - B) / 2.
Notice that A and B should be of same odditiy, either both odd or both even, otherwise in last formulas above we can't have whole division by 2.
We will factorize N into all possible pairs of two factors (A, B) of same oddity. For fast factorization in code below I used simple to implement but yet quite fast algorithm Pollard Rho, also two extra algorithms were needed as a helper to Pollard Rho, one is Fermat Primality Test (which allows fast checking if number is probably prime) and second is Trial Division Factorization (which helps Pollard Rho to factor out small factors, which could cause Pollard Rho to fail).
Pollard Rho for composite number has time complexity O(N^(1/4)) which is very fast even for 64-bit numbers. Any faster factorization algorithm can be chosen if needed a bigger space to be searched. My fast algorithm time is dominated by speed of factorization, remaining part of algorithm is blazingly fast, just few iterations of loop with simple formulas.
If your N is a square itself (hence we know its root easily), then Pollard Rho can factor N even much faster, within O(N^(1/8)) time. Even for 128-bit numbers it means very small time, 2^16 operations, and I hope you're solving your task for less than 128 bit numbers.
If you want to process a range of possible N values then fastest way to factorize them is to use techniques similar to Sieve of Erathosthenes, using set of prime numbers, it allows to compute all factors for all N numbers within some range. Using Sieve of Erathosthenes for the case of range of Ns is much faster than factorizing each N with Pollard Rho.
After factoring N into pairs (A, B) we compute (X, Y) based on (A, B) by formulas above. And output resulting Y as a solution of fast algorithm.
Following code as an example is implemented in pure Python. Of course one can use Numba to speed it up, Numba usually gives 30-200 times speedup, for Python it achieves same speed as optimized C++. But I thought that main thing here is to implement fast algorithm, Numba optimizations can be done easily afterwards.
I added time measurement into following code. Although it is pure Python still my fast algorithm achieves 8500x times speedup compared to regular brute force approach for limit of 1 000 000.
You can change limit variable to tweak amount of searched space, or num_tests variable to tweak amount of different tests.
Following code implements both solutions - fast solution find_fast() described above plus very tiny brute force solution find_slow() which is very slow as it scans all possible candidates. This slow solution is only used to compare correctness in tests and compare speedup.
Code below uses nothing except few standard Python library modules, no external modules were used.
Try it online!
def find_slow(N):
import math
def is_square(x):
root = int(math.sqrt(float(x)) + 0.5)
return root * root == x, root
l = []
for y in range(N):
if is_square(N + y ** 2)[0]:
l.append(y)
return l
def find_fast(N):
import itertools, functools
Prod = lambda it: functools.reduce(lambda a, b: a * b, it, 1)
fs = factor(N)
mfs = {}
for e in fs:
mfs[e] = mfs.get(e, 0) + 1
fs = sorted(mfs.items())
del mfs
Ys = set()
for take_a in itertools.product(*[
(range(v + 1) if k != 2 else range(1, v)) for k, v in fs]):
A = Prod([p ** t for (p, _), t in zip(fs, take_a)])
B = N // A
assert A * B == N, (N, A, B, take_a)
if A < B:
continue
X = (A + B) // 2
Y = (A - B) // 2
assert N + Y ** 2 == X ** 2, (N, A, B, X, Y)
Ys.add(Y)
return sorted(Ys)
def trial_div_factor(n, limit = None):
# https://en.wikipedia.org/wiki/Trial_division
fs = []
while n & 1 == 0:
fs.append(2)
n >>= 1
all_checked = False
for d in range(3, (limit or n) + 1, 2):
if d * d > n:
all_checked = True
break
while True:
q, r = divmod(n, d)
if r != 0:
break
fs.append(d)
n = q
if n > 1 and all_checked:
fs.append(n)
n = 1
return fs, n
def fermat_prp(n, trials = 32):
# https://en.wikipedia.org/wiki/Fermat_primality_test
import random
if n <= 16:
return n in (2, 3, 5, 7, 11, 13)
for i in range(trials):
if pow(random.randint(2, n - 2), n - 1, n) != 1:
return False
return True
def pollard_rho_factor(n):
# https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm
import math, random
fs, n = trial_div_factor(n, 1 << 7)
if n <= 1:
return fs
if fermat_prp(n):
return sorted(fs + [n])
for itry in range(8):
failed = False
x = random.randint(2, n - 2)
for cycle in range(1, 1 << 60):
y = x
for i in range(1 << cycle):
x = (x * x + 1) % n
d = math.gcd(x - y, n)
if d == 1:
continue
if d == n:
failed = True
break
return sorted(fs + pollard_rho_factor(d) + pollard_rho_factor(n // d))
if failed:
break
assert False, f'Pollard Rho failed! n = {n}'
def factor(N):
import functools
Prod = lambda it: functools.reduce(lambda a, b: a * b, it, 1)
fs = pollard_rho_factor(N)
assert N == Prod(fs), (N, fs)
return sorted(fs)
def test():
import random, time
limit = 1 << 20
num_tests = 20
t0, t1 = 0, 0
for i in range(num_tests):
if (round(i / num_tests * 1000)) % 100 == 0 or i + 1 >= num_tests:
print(f'test {i}, ', end = '', flush = True)
N = random.randrange(limit)
tb = time.time()
r0 = find_slow(N)
t0 += time.time() - tb
tb = time.time()
r1 = find_fast(N)
t1 += time.time() - tb
assert r0 == r1, (N, r0, r1, t0, t1)
print(f'\nTime slow {t0:.05f} sec, fast {t1:.05f} sec, speedup {round(t0 / max(1e-6, t1))} times')
if __name__ == '__main__':
test()
Output:
test 0, test 2, test 4, test 6, test 8, test 10, test 12, test 14, test 16, test 18, test 19,
Time slow 26.28198 sec, fast 0.00301 sec, speedup 8732 times
For the easiest solution, you can try this:
import math
n=13689 #or we can ask user to input a square number.
for i in range(1,9999):
if math.sqrt(n+i**2).is_integer():
print(i)

Is there anyway to make this code to run faster [duplicate]

This question already has answers here:
calculate mod using pow function python
(3 answers)
Closed 1 year ago.
Is there any way to make this code run faster?
g = 53710316114328094
a = 995443176435632644
n = 926093738455418579
print(g**a%n)
It is running for too long I want to make it faster
I also tried:
import math
g = 53710316114328094
a = 995443176435632644
n = 926093738455418579
print(math.pow(g**a)%n)
and
g = 53710316114328094
a = 995443176435632644
n = 926093738455418579
def power(a,b):
ans = 1
for i in range(b):
ans *= a
return ans
print(power(g,a)%n)
All of these code is running for very long
First of all you need to know about Binary exponentiation algorithm. The idea is that instead of computing e.g. 5^46 like 5*5*5*5... 46 times, you can do
5^46 == 5^2 * 5^4 * 5^8 * 5^32
The key here, is that you can compute 5^2 fast from 5 (just square it), then 5^4 fast from 5^2 (just square it), then 5^8 from 5^4 (just square it) and so on. To determine which 5^K numbers you should multiply and which not, you can represent the power as a binary number, and multiply to the final result only those components, that correspond to 1 in this binary representation. E.g.
decimal 46 == binary 101110
Thus
5^1 is skipped (corresponds to right most 0), 5^2 is multiplied (corresponds to right most 1), 5^4 is multiplied(second from the right 1), 5^8 is multiplied (third from the right 1), 5^16 is skipped (the left most 0) and 5^32 is multiplied (the left most 1).
Next, you need to compute a very huge power, it's impractically big. But there is a shortcut, since you use modulo operation.
You see, there's a rule that
(a*b % n) == ( (a % n)*(b % n) ) % n
So these should be equivalent
5^46 % n == ( ( ( (5^2 % n) * (5^4 % n) % n) * (5^8 % n) % n) * (5^32 % n) % n)
Notice that each number we multiply won't ever exceed n, so the overall multiplication chain will not take forever, as n is big, but not even remotely as gigantic as g**a
In the code, all of that looks like that. It computes instantly
def pow_modulo_n(base, power, n):
result = 1
multiplier = base
while power > 0:
power, binary_digit = divmod(power, 2)
if binary_digit == 1:
result = (result * multiplier) % n
multiplier = (multiplier**2) % n
return result % n
g = 53710316114328094
a = 995443176435632644
n = 926093738455418579
print(pow_modulo_n(g, a, n))
This prints
434839845697636246

Counting number of ways I can have unique numbers in array

I am trying to find the number of ways to construct an array such that consecutive positions contain different values.
Specifically, I need to construct an array with elements such that each element 1 between and k , all inclusive. I also want the first and last elements of the array to be 1 and x.
Complete problem statement:
Here is what I tried:
def countArray(n, k, x):
# Return the number of ways to fill in the array.
if x > k:
return 0
if x == 1:
return 0
def fact(n):
if n == 0:
return 1
fact_range = n+1
T = [1 for i in range(fact_range)]
for i in range(1,fact_range):
T[i] = i * T[i-1]
return T[fact_range-1]
ways = fact(k) / (fact(n-2)*fact(k-(n-2)))
return int(ways)
In short, I did K(C)N-2 to find the ways. How could I solve this?
It passes one of the base case with inputs as countArray(4,3,2) but fails for 16 other cases.
Let X(n) be the number of ways of constructing an array of length n, starting with 1 and ending in x (and not repeating any numbers). Let Y(n) be the number of ways of constructing an array of length n, starting with 1 and NOT ending in x (and not repeating any numbers).
Then there's these recurrence relations (for n>1)
X(n+1) = Y(n)
Y(n+1) = X(n)*(k-1) + Y(n)*(k-2)
In words: If you want an array of length n+1 ending in x, then you need an array of length n not ending in x. And if you want an array of length n+1 not ending in x, then you can either add any of the k-1 symbols to an array of length n ending in x, or you can take an array of length n not ending in x, and add any of the k-2 symbols that aren't x and don't repeat the last value.
For the base case, n=1, if x is 1 then X(1)=1, Y(1)=0 otherwise, X(1)=0, Y(1)=1
This gives you an O(n)-time method of computing the result.
def ways(n, k, x):
M = 10**9 + 7
wx = (x == 1)
wnx = (x != 1)
for _ in range(n-1):
wx, wnx = wnx, wx * (k-1) + wnx*(k-2)
wnx = wnx % M
return wx
print(ways(100, 5, 2))
In principle you can reduce this to O(log n) by expressing the recurrence relations as a matrix and computing the matrix power (mod M), but it's probably not necessary for the question.
[Additional working]
We have the recurrence relations:
X(n+1) = Y(n)
Y(n+1) = X(n)*(k-1) + Y(n)*(k-2)
Using the first, we can replace the Y(_) in the second with X(_+1) to reduce it down to a single variable. Then:
X(n+2) = X(n)*(k-1) + X(n+1)*(k-2)
Using standard techniques, we can solve this linear recurrence relation exactly.
In the case x!=1, we have:
X(n) = ((k-1)^(n-1) - (-1)^n) / k
And in the case x=1, we have:
X(n) = ((k-1)^(n-1) - (1-k)(-1)^n)/k
We can compute these mod M using Fermat's little theorem because M is prime. So 1/k = k^(M-2) mod M.
Thus we have (with a little bit of optimization) this short program that solves the problem and runs in O(log n) time:
def ways2(n, k, x):
S = -1 if n%2 else 1
return ((pow(k-1, n-1, M) + S) * pow(k, M-2, M) - S*(x==1)) % M
could you try this DP version: (it's passed all tests) (it's inspired by #PaulHankin and take DP approach - will run performance later to see what's diff for big matrix)
def countArray(n, k, x):
# Return the number of ways to fill in the array.
big_mod = 10 ** 9 + 7
dp = [[1], [1]]
if x == 1:
dp = [[1], [0]]
else:
dp = [[1], [1]]
for _ in range(n-2):
dp[0].append(dp[0][-1] * (k - 1) % big_mod)
dp[1].append((dp[0][-1] - dp[1][-1]) % big_mod)
return dp[1][-1]

Finding remainder mod involving exponent and division involving huge numbers

I need a fast algorithm to evaluate the following
((a^n-1)/(a-1)) % p
Both a and n are nearly equal but less to 10^6 and p is a fixed prime number (let's say p=1000003). I need to compute it under 1 second. I am using python. Wolfram Mathematica computes it instantly. It takes 35.2170000076 seconds with following code
print (((10**6)**(10**6)-1)/((10**6)-1))%1000003
If that denominator a-1 were not present, I could group the powers into smaller order and use the relation a*b (mod c) = (a (mod c) * b (mod c)) (mod c) but denominator is present.
How to evaluate this with a fast algorithm? No numpy/scipy are available.
UPDATE:: Here is the final code I came up with
def exp_div_mod(a, n, p):
r = pow(a, n, p*(a-1)) - 1
r = r - 1 if r == -1 else r
return r/(a-1)
(((a ** n) - 1) / (a-1)) % p
can be rewritten as
(((a ** n) - 1) % ((a-1)*p)) / (a-1)
This part:
(((a ** n) - 1) % ((a-1)*p))
can be computed by calculating this:
((a ** n) % ((a-1)*p))
and then adjusting for the -1 afterwards.
Raise a by to the nth power and mod by ((a-1)*p). This can be done using the Python pow() function. Then adjust for the -1 and divide by a-1.
Using the pow() function and passing a modulo value is faster than computing the full exponent and then taking the modulo, because the modulo can be applied to the partial products at each stage of the calculation, which stops the value from getting too large (106 to the power of 106 has 6 million decimal digits, with a modulo applied at each step the values never have to grow larger than the size of the modulo - about 13 digits in this example).
Code:
def exp_div_mod(a, n, p):
m = p * (a - 1)
return ((pow(a, n, m) - 1) % m) // (a - 1);
print exp_div_mod((10**6), (10**6), 1000003)
output:
444446
Note: this approach only works if a, n and p are integers.
(an−1) ⁄ (a−1) is the sum from i = 0 to n−1 of ai.
Computing the latter mod p is straightforward, based on the following:
let F(a, n) be Σ(i=0..n-1){ai} if n > 0, otherwise 0.
Now:
F(a,n) = a×F(a,n−1) + 1
F(a,2n) = (a+1)×F(a2,n)
The second identity is the divide-and-conquer recursion.
Since both of these only involve addition and multiplication, we can compute them mod p without needing an integer type larger than a×p by distributing the modulus operation. (See code below.)
With just the first recursion, we can code an iterative solution:
def sum_of_powers(a, n, p):
sum = 0
for i in range(n): sum = (a * sum + 1) % p
return sum
Using the divide-and-conquer recursion as well, we arrive at something not much more complicated:
def sum_of_powers(a, n, p):
if n % 2 == 1:
return (a * sum_of_powers(a, n-1, p) + 1) % p
elif n > 0:
return ((a + 1) * sum_of_powers(a * a % p, n // 2, p)) % p
else:
return 0
The first solution returns in less than a second with n == 106. The second one returns instantly, even with n as large as 109.
You can multiply by the modular inverse of p - 1. Due to Fermat's little theorem, you have xp-2 · x ≡ xp-1 ≡ 1 (mod p) for all 0 < x < p, so you don't even need extended Euclid to compute the inverse, just the pow function from standard Python:
(pow(a, n, p) - 1) * pow(a - 1, p - 2, p) % p
The algorithm has time complexity 𝒪(log p) because square-and-multiply is used.

Computing Eulers Totient Function

I am trying to find an efficient way to compute Euler's totient function.
What is wrong with this code? It doesn't seem to be working.
def isPrime(a):
return not ( a < 2 or any(a % i == 0 for i in range(2, int(a ** 0.5) + 1)))
def phi(n):
y = 1
for i in range(2,n+1):
if isPrime(i) is True and n % i == 0 is True:
y = y * (1 - 1/i)
else:
continue
return int(y)
Here's a much faster, working way, based on this description on Wikipedia:
Thus if n is a positive integer, then φ(n) is the number of integers k in the range 1 ≤ k ≤ n for which gcd(n, k) = 1.
I'm not saying this is the fastest or cleanest, but it works.
from math import gcd
def phi(n):
amount = 0
for k in range(1, n + 1):
if gcd(n, k) == 1:
amount += 1
return amount
You have three different problems...
y needs to be equal to n as initial value, not 1
As some have mentioned in the comments, don't use integer division
n % i == 0 is True isn't doing what you think because of Python chaining the comparisons! Even if n % i equals 0 then 0 == 0 is True BUT 0 is True is False! Use parens or just get rid of comparing to True since that isn't necessary anyway.
Fixing those problems,
def phi(n):
y = n
for i in range(2,n+1):
if isPrime(i) and n % i == 0:
y *= 1 - 1.0/i
return int(y)
Calculating gcd for every pair in range is not efficient and does not scales. You don't need to iterate throught all the range, if n is not a prime you can check for prime factors up to its square root, refer to https://stackoverflow.com/a/5811176/3393095.
We must then update phi for every prime by phi = phi*(1 - 1/prime).
def totatives(n):
phi = int(n > 1 and n)
for p in range(2, int(n ** .5) + 1):
if not n % p:
phi -= phi // p
while not n % p:
n //= p
#if n is > 1 it means it is prime
if n > 1: phi -= phi // n
return phi
I'm working on a cryptographic library in python and this is what i'm using. gcd() is Euclid's method for calculating greatest common divisor, and phi() is the totient function.
def gcd(a, b):
while b:
a, b=b, a%b
return a
def phi(a):
b=a-1
c=0
while b:
if not gcd(a,b)-1:
c+=1
b-=1
return c
Most implementations mentioned by other users rely on calling a gcd() or isPrime() function. In the case you are going to use the phi() function many times, it pays of to calculated these values before hand. A way of doing this is by using a so called sieve algorithm.
https://stackoverflow.com/a/18997575/7217653 This answer on stackoverflow provides us with a fast way of finding all primes below a given number.
Oke, now we can replace isPrime() with a search in our array.
Now the actual phi function:
Wikipedia gives us a clear example: https://en.wikipedia.org/wiki/Euler%27s_totient_function#Example
phi(36) = phi(2^2 * 3^2) = 36 * (1- 1/2) * (1- 1/3) = 30 * 1/2 * 2/3 = 12
In words, this says that the distinct prime factors of 36 are 2 and 3; half of the thirty-six integers from 1 to 36 are divisible by 2, leaving eighteen; a third of those are divisible by 3, leaving twelve numbers that are coprime to 36. And indeed there are twelve positive integers that are coprime with 36 and lower than 36: 1, 5, 7, 11, 13, 17, 19, 23, 25, 29, 31, and 35.
TL;DR
With other words: We have to find all the prime factors of our number and then multiply these prime factors together using foreach prime_factor: n *= 1 - 1/prime_factor.
import math
MAX = 10**5
# CREDIT TO https://stackoverflow.com/a/18997575/7217653
def sieve_for_primes_to(n):
size = n//2
sieve = [1]*size
limit = int(n**0.5)
for i in range(1,limit):
if sieve[i]:
val = 2*i+1
tmp = ((size-1) - i)//val
sieve[i+val::val] = [0]*tmp
return [2] + [i*2+1 for i, v in enumerate(sieve) if v and i>0]
PRIMES = sieve_for_primes_to(MAX)
print("Primes generated")
def phi(n):
original_n = n
prime_factors = []
prime_index = 0
while n > 1: # As long as there are more factors to be found
p = PRIMES[prime_index]
if (n % p == 0): # is this prime a factor?
prime_factors.append(p)
while math.ceil(n / p) == math.floor(n / p): # as long as we can devide our current number by this factor and it gives back a integer remove it
n = n // p
prime_index += 1
for v in prime_factors: # Now we have the prime factors, we do the same calculation as wikipedia
original_n *= 1 - (1/v)
return int(original_n)
print(phi(36)) # = phi(2**2 * 3**2) = 36 * (1- 1/2) * (1- 1/3) = 36 * 1/2 * 2/3 = 12
It looks like you're trying to use Euler's product formula, but you're not calculating the number of primes which divide a. You're calculating the number of elements relatively prime to a.
In addition, since 1 and i are both integers, so is the division, in this case you always get 0.
With regards to efficiency, I haven't noticed anyone mention that gcd(k,n)=gcd(n-k,n). Using this fact can save roughly half the work needed for the methods involving the use of the gcd. Just start the count with 2 (because 1/n and (n-1)/k will always be irreducible) and add 2 each time the gcd is one.
Here is a shorter implementation of orlp's answer.
from math import gcd
def phi(n): return sum([gcd(n, k)==1 for k in range(1, n+1)])
As others have already mentioned it leaves room for performance optimization.
Actually to calculate phi(any number say n)
We use the Formula
where p are the prime factors of n.
So, you have few mistakes in your code:
1.y should be equal to n
2. For 1/i actually 1 and i both are integers so their evaluation will also be an integer,thus it will lead to wrong results.
Here is the code with required corrections.
def phi(n):
y = n
for i in range(2,n+1):
if isPrime(i) and n % i == 0 :
y -= y/i
else:
continue
return int(y)

Categories