Proper Carmichael Function - python

I'm creating all the necessary functions for RSA algorithm. Unfortunately i can't seem to a make proper Carmichael function.
These are the functions that i've written:
def gcd(a, b): # Greatest Common Divisor Generator (Euclidean Algorithm)
while b != 0: # While remainder exists
t = b # Initially r[k-1]
b = a % t # Initially r[k] = r[k-2] mod r[k-1] (where r[k-2] is a)
a = t # Predecessor of remainder (b)
return a
def phi(n): # Leonard Euler's Totient Function
y = 0
for k in range(1, n + 1): # Phi(+n) is the number of integers k in the range (1 <= k >= n)...
if gcd(n, k) == 1: # for which gcd(n, k) = 1
y += 1
return y
def carmichael(n): # Robert Daniel Carmichael's Function
y = (phi(n) * 1/2) if (n > 4 and ((n & (n - 1)) == 0)) else phi(n) # phi(n) * 1/2 if 2^x = n, else phi(n) * 1
return y
I'm using totient function for number generation. From my knowledge there is a simple rule, If number is power of 2 and it's greater than 4, Amount of it's prime numbers shall be halved, otherwise it's equal to phi(n).
The rule above is perfectly working in my code, For example, if the input value is 8, these are the results:
phi(8) = 4
carmichael(8) = 2
But the problem is, Carmichael function is also halving other numbers for some reason, for example if input is 12, this is what my functions return:
phi(12) = 4
carmichael(12) = 4
But this is how it should look like:
phi(12) = 4
carmichael(12) = 2
Why is this happening? Perhaps non-prime odd numbers should be treated differently? Is there something that i need to add to my function?
Thank you!

First we create the gcd function to calculate greatest common divisor of 2 numbers, we will need it later in lambda function.
def gcd(a,b):
while (a>0):
b=b%a
(a,b)=(b,a)
return b
Then we look at how carmichael function works.
Let n be a positive integer. Then λ(n) is defined to be the smallest positive integer k such that
a^k≡1(mod n)
for all a such that gcd(a,n)=1.
Note that we are looking for k, the values of a is determined once we have n.
Now we initialize the function with default condition
n=int(n)
k=2
a=1
alist=[]
To find all a values we use gcd(a,n)=1 to test whether a and n have the greatest common divisor as 1, which means they are coprime.
If not, a++
if gcd(a,n)==1, we store this value to the list of a and test next a until we test all a<=n
while not ((gcd(a,n))==1):
a=a+1
while ((gcd(a,n))==1) & (a<=n) :
alist.append(a)
a=a+1
while not ((gcd(a,n))==1):
a=a+1
Ok now we have all a in the list alist, look back at definition
the smallest positive integer k such that
a^k≡1(mod n)
First we count the number of a, which is the length of alist
timer=len(alist)
Then we use
if (a**k)%n==1:
to test whether this k makes a^k≡1(mod n) for all a value in alist. We construct a loop
for a in alist:
if (a**k)%n==1:
timer=timer-1
if timer <0:
break
pass
else:
timer=len(alist)
k=k+1
to test all k number from 2, if it doesnot meet requirement, we do k=k+1
Now we have the whole function as following
def carmichael(n):
n=int(n)
k=2
a=1
alist=[]
while not ((gcd(a,n))==1):
a=a+1
while ((gcd(a,n))==1) & (a<=n) :
alist.append(a)
a=a+1
while not ((gcd(a,n))==1):
a=a+1
timer=len(alist)
while timer>=0:
for a in alist:
if (a**k)%n==1:
timer=timer-1
if timer <0:
break
pass
else:
timer=len(alist)
k=k+1
return k

Related

How to define a variable by an equation containing it? (Python)

I´m solving a problem in which i have to print all the fibonacci numbers such that:
a <= f <= b
And i would like to start them by the smallest fibonacci number that is greater than or equal to a, in order to make my program run faster. For that, i need to define a variable "n", such that the nth Fibonacci number satisfies the condition above (smallest one that is greater than or equal to a). To define such variable, i need to find the smallest "n" that satisfies the fibonacci(n) general term equation.
I tried to find it by making a for loop, but it just ends up being as slow as if i started to check from the first Fibonacci Number. Anyone has any ideas on how to define it efficiently?
P.S. Here is my attempted code:
from math import sqrt, log, ceil
def Fibo(n):
if n == 1: return 1
elif n == 2: return 2
return Fibo(n-1) + Fibo(n-2)
while True:
try:
a, b = [int(i) for i in input().split()]
cont = 0
phi = (sqrt(5) + 1) / 2
i = ceil(log(a * sqrt(5), phi))
if Fibo(i-1) >= a: i -= 1
elif Fibo(n) < a: i += 1
while True:
if a <= Fibo(i) <= b: cont += 1
elif Fibo(i) > b:
break
i -= 1
print(cont)
except input() == "0 0":
break
Probably the most useful formula for your purpose for F(n), the nth Fibonacci number, is
from math import sqrt
phi = (sqrt(5) + 1) / 2 # the golden ratio
F(n) = round(phi**n / sqrt(5))
Therefore, one formula to get the value of n for a given value of a is
from math import sqrt, log, ceil
phi = (sqrt(5) + 1) / 2 # the golden ratio
n = ceil(log(a * sqrt(5), phi))
Due to approximation and rounding issues, you should check the values of n-1, n, and n+1 to ensure you got exactly the desired value. If you do this often, you should pre-define variables holding the value of the golden ratio and of the square root of five. If your value of a is too large for the float type to store it accurately, you would need a more complicated routine to handle the larger number.

Optimizing a python Code

I'm trying to optimize this code (Given two integers m, n (1 <= m <= n) we want to find all integers between m and n whose sum of squared divisors is itself a square). I'm new to coding and I'm having a hard time with this concept
def list_squared(m, n):
# your code
import math
MyList = []
for i in range(m,n):
A=[]
for k in range(1,i+1):
if i%k == 0:
A.append(k**2)
if round(math.sqrt(sum(A))) == math.sqrt(sum(A)):
B =[]
B.append(i)
B.append(sum(A))
MyList.append(B)
return MyList
import math
def list_squared(m, n):
MyList = []
for i in range(m,n):
res=0
for k in range(1,i+1):
if i%k == 0:
res+=k**2
if res == int(math.sqrt(res))**2
MyList.append(i)
return MyList
First thing that i note you can optimize is range(1,i+1). You can set initially res=1 and start the range from 2 avoiding the first cycle. The important optimization is in the end: you can stop after i/2 because there are not integer divisors after it but remember to include the dispair case (for example 3/2 = 1.5 is not a valid input for range) so wrap the result of division around ceil function. In conclusion a simple optimization is range(2, ceil(i/2)+1) with res=1

Refining Factors in Python

I have to write a function factor, which takes an integer parameter n, and returns the least number from 2 through n-1 that divides n. If no such number exists, it returns -1.
I was able to create the function to find the factors, but am unsure on how to refine it to return the correct result.
def factors(n):
i = n
lst=[]
while i > 0:
if n % i == 0:
lst.append(i)
i -= 1
print(lst)
result=[i for i in lst if i > 2 and i < n-1]
print(result[1])
def main():
n=int(input("Enter n:"))
factors(n)
main()
You can use list comprehension to find the factors of a number. Also, to optimize your solution, you only need to run until half of the number.
e.g. for 12, the maximum factor of 12 can be 6.
A number greater than half of that number can't be its factor. So, you do not require to run your loop until n-1.
>>> [n for n in range(2, number/2+1) if number % n == 0]
In the above line, we will run a loop from 2 to (number/2 + 1) and check if the number is divisible by n, then add it to the list.
Your factor function should look from the smallest value first, then start increasing
def factor(n):
i = 2
while i < n:
if n % i == 0:
return i
i += 1
return -1
>>> factor(6)
2
>>> factor(21)
3
>>> factor(49)
7
>>> factor(13)
-1
Then factors can call that
def factors(n):
values = [1]
while n > 1:
f = factor(n)
if f > -1:
values.append(f)
n //= f
else:
values.append(n)
break
return values
>>> factors(21)
[1, 3, 7]
You're doing a lot of unnecessary work here: you find all factors, instead of just the smallest. However, you do have a correct answer at your fingertips: you print the second element as the lowest factor, but your list is in the opposite order. Try
print lst[-2]
That said you really should not bother with all of that. Instead, start at 2 and work upward, looking for the smallest factor. If you get to sqrt(n) without finding any, return a result of -1.
Here is optimized way for finding factor of a number in between 2 or n-1:
def factor(n):
i=2
a=[]
while i*i<=n:
if n%i==0:
if i!=n/i:
a.append(i)
a.append(n/i)
else:
a.append(i)
i+=1
a.sort()
print a
n=int(input())
factor(n)

How would you implement a divisor function?

The divisor function is the sum of divisors of a natural number.
Making a little research I found this to be a very good method if you want to find the divisor function of a given natural number N, so I tried to code it in Python:
def divisor_function(n):
"Returns the sum of divisors of n"
checked = [False]*100000
factors = prime_factors(n)
sum_of_divisors = 1 # It's = 1 because it will be the result of a product
for x in factors:
if checked[x]:
continue
else:
count = factors.count(x)
tmp = (x**(count+1)-1)//(x-1)
sum_of_divisors*=tmp
checked[x]=True
return sum_of_divisors
It works pretty well,but I am sure that it can be improved(e.g. : I create a list with 100000 elements,but I am not using most of them).
How would you improve/implement it?
P.S. This is prime_factors:
def prime_factors(n):
"Returns all the prime factors of a positive integer"
factors = []
d = 2
while (n > 1):
while (n%d==0):
factors.append(d)
n /= d
d = d + 1
if (d*d>n):
if (n>1): factors.append(int(n));
break;
return factors
When computing the sum of divisors, you need the factorization of n in the form p1k1 p2k2 ... — that is, you need the exponent of each prime in the factorization. At the moment you are doing this by computing a flat list of prime factors, and then calling count to work out the exponent. This is a waste of time because you can easily generate the prime factorization in the format you need in the first place, like this:
def factorization(n):
"""
Generate the prime factorization of n in the form of pairs (p, k)
where the prime p appears k times in the factorization.
>>> list(factorization(1))
[]
>>> list(factorization(24))
[(2, 3), (3, 1)]
>>> list(factorization(1001))
[(7, 1), (11, 1), (13, 1)]
"""
p = 1
while p * p < n:
p += 1
k = 0
while n % p == 0:
k += 1
n //= p
if k:
yield p, k
if n != 1:
yield n, 1
Notes on the code above:
I've transformed this code so that it generates the factorization, instead of constructing a list (by repeated calls to append) and returning it. In Python, this transformation is nearly always an improvement, because it allows you to consume elements one by one as they are generated, without having to store the whole sequence in memory.
This is the kind of function for which doctests work well.
Now computing the sum of divisors is really simple: there's no need to store the set of checked factors or to count the number of times each factor occurs. In fact you can do it in just one line:
from operator import mul
def sum_of_divisors(n):
"""
Return the sum of divisors of n.
>>> sum_of_divisors(1)
1
>>> sum_of_divisors(33550336) // 2
33550336
"""
return reduce(mul, ((p**(k+1)-1) // (p-1) for p, k in factorization(n)), 1)
You need to change two lines only:
def divisor_function(n):
"Returns the sum of divisors of n"
checked = {}
factors = prime_factors(n)
sum_of_divisors = 1 # It's = 1 because it will be the result of a product
for x in factors:
if checked.get(x,False):
continue
else:
count = factors.count(x)
tmp = (x**(count+1)-1)//(x-1)
sum_of_divisors*=tmp
checked[x]=True
return sum_of_divisors
why use dict or set - or count() - at all, when prime_factors() is guaranteed to return the factors in ascending order? You only ever deal with a previous factor. Counting can just be a part of iteration:
def divisor_function(n):
"Returns the sum of divisors of n"
factors = prime_factors(n)
sum_of_divisors = 1
count = 0; prev = 0;
for x in factors:
if x==prev:
count += 1
else:
if prev: sum_of_divisors *= (prev**(count+1)-1)//(prev-1)
count = 1; prev = x;
if prev: sum_of_divisors *= (prev**(count+1)-1)//(prev-1)
return sum_of_divisors
def sum_divisors(n):
assert n > 0
if n == 1:
return 0
sum = 1
if n % 2 == 0: # if n is even there is a need to go over even numbers
i = 2
while i < sqrt (n):
if n % i == 0:
sum = sum + i + (n//i) # if i|n then n/i is an integer so we want to add it as well
i = i + 1
if type (sqrt (n)) == int: # if sqrt(n)|n we would like to avoid adding it twice
sum = sum + sqrt (n)
else:
i = 3
while i < sqrt (n): # this loop will only go over odd numbers since 2 is not a factor
if n % i == 0:
sum = sum + i + (n//i) # if i|n then n/i is an integer so we want to add it as well
i = i + 2
if type (sqrt (n)) == int: # if sqrt(n)|n we would like to avoid adding it twice
sum = sum + sqrt (n)
return sum
Here is what I do in my Java number utilities (extensively used for Project Euler):
Generate the prime factorization with explicit exponents (see the answer by Gareth Rees).
Unfold the prime factorization in the various functions based on it. I.e., use the same algorithm as for prime factorization but directly compute the desire value instead of storing the factors and exponents.
By default test only divisors two and odd numbers. I have methods firstDivisor(n) and nextDivisor(n,d) for that.
Optionally precompute a table of least divisors for all numbers below a bound. This is very useful if you need to factorize all or most numbers below the bound (improves speed by about sqrt(limit)). I hook the table into the firstDivisor(n) and nextDivisor(n,d) methods, so this doesn't change the factorization algorithms.

How do you implement the divisor function in code?

Overall Problem: Project Euler 12 - What is the value of the first triangle number to have over five hundred divisors?
Focus of problem: The divisor function
Language: Python
Description: The function I used is brute and the time it take for the program to find a number with more divisors than x increases almost exponentially with each 10 or 20 numbers highers. I need to get to 500 or more divisors. I've identified that the divisor function is what is hogging down the program. The research I did lead me to divisor functions and specifically the divisor function which is supposed to be a function that will count all the divisors of any integer. Every page I've looked at seems to be directed toward mathematics majors and I only have high-school maths. Although I did come across some page that mentioned allot about primes and the Sieve of Atkins but I could not make the connection between primes and finding all the divisors of any integer nor find anything on the net about it.
Main Question: Could someone explain how to code the divisor function or even provide a sample? Maths concepts make more sense to me when I look at them with code. So much appreciated.
brute force divisor function:
def countdiv(a):
count = 0
for i in range(1,(a/2)+1):
if a % i == 0:
count += 1
return count + 1 # +1 to account for number itself as a divisor
If you need a bruteforce function to calculate Number of Divisors (also known as tau(n))
Here's what it looks like
def tau(n):
sqroot,t = int(n**0.5),0
for factor in range(1,sqroot+1):
if n % factor == 0:
t += 2 # both factor and N/factor
if sqroot*sqroot == n: t = t - 1 # if sqroot is a factor then we counted it twice, so subtract 1
return t
The second method involves a decomposing n into its prime factors (and its exponents).
tau(n) = (e1+1)(e2+1)....(em+1) where n = p1^e1 * p2^e2 .... pm^em and p1,p2..pm are primes
More info here
The third method and much more simpler to understand is simply using a Sieve to calculate tau.
def sieve(N):
t = [0]*(N+1)
for factor in range(1,N+1):
for multiple in range(factor,N+1,factor):
t[multiple]+=1
return t[1:]
Here's it in action at ideone
I agree with the two other answers submitted here in that you will only need to search up to the square root of the number. I have one thing to add to this however. The solutions offered will get you the correct answer in a reasonable amount of time. But when the problems start getting tougher, you will need an even more powerful function.
Take a look at Euler's Totient function. Though it only indirectly applies here, it is incredibly useful in later problems. Another related concept is that of Prime Factorization.
A quick way to improve your algorithm is to find the prime factorization of the number. In the Wikipedia article, they use 36 as an example, whose prime factorization is 2^2 * 3^2. Therefore, knowing this, you can use combinatorics to find the number of factors of 36. With this, you will not actually be computing each factor, plus you'd only have to check divisors 2 and 3 before you're complete.
When searching for divisors of n you never have to search beyond the square root of the number n. Whenever you find a divisor that's less than sqrt(n) there is exactly one matching divisor which is greater than the root, so you can increment your count by 2 (if you find divisor d of n then n/d will be the counterpart).
Watch out for square numbers, though. :) The root will be a divisor that doesn't count twice, of course.
If you're going to solve the Project Euler problems you need some functions that deal with prime numbers and integer factorization. Here is my modest library, which provides primes(n), is_prime(n) and factors(n); the focus is on simplicity, clarity and brevity at the expense of speed, though these functions should be sufficient for Project Euler:
def primes(n):
"""
list of primes not exceeding n in ascending
order; assumes n is an integer greater than
1; uses Sieve of Eratosthenes
"""
m = (n-1) // 2
b = [True] * m
i, p, ps = 0, 3, [2]
while p*p < n:
if b[i]:
ps.append(p)
j = 2*i*i + 6*i + 3
while j < m:
b[j] = False
j = j + 2*i + 3
i += 1; p += 2
while i < m:
if b[i]:
ps.append(p)
i += 1; p += 2
return ps
def is_prime(n):
"""
False if n is provably composite, else
True if n is probably prime; assumes n
is an integer greater than 1; uses
Miller-Rabin test on prime bases < 100
"""
ps = [2,3,5,7,11,13,17,19,23,29,31,37,41,
43,47,53,59,61,67,71,73,79,83,89,97]
def is_spsp(n, a):
d, s = n-1, 0
while d%2 == 0:
d /= 2; s += 1
if pow(a,d,n) == 1:
return True
for r in xrange(s):
if pow(a, d*pow(2,r), n) == n-1:
return True
return False
if n in ps: return True
for p in ps:
if not is_spsp(n,p):
return False
return True
def factors(n):
"""
list of prime factors of n in ascending
order; assumes n is an integer, may be
positive, zero or negative; uses Pollard's
rho algorithm with Floyd's cycle finder
"""
def gcd(a,b):
while b: a, b = b, a%b
return abs(a)
def facts(n,c,fs):
f = lambda(x): (x*x+c) % n
if is_prime(n): return fs+[n]
t, h, d = 2, 2, 1
while d == 1:
t = f(t); h = f(f(h))
d = gcd(t-h, n)
if d == n:
return facts(n, c+1, fs)
if is_prime(d):
return facts(n//d, c+1, fs+[d])
return facts(n, c+1, fs)
if -1 <= n <= 1: return [n]
if n < -1: return [-1] + factors(-n)
fs = []
while n%2 == 0:
n = n//2; fs = fs+[2]
if n == 1: return fs
return sorted(facts(n,1,fs))
Once you know how to factor a number, it is easy to count the number of divisors. Consider 76576500 = 2^2 * 3^2 * 5^3 * 7^1 * 11^1 * 13^1 * 17^1. Ignore the bases and look at the exponents, which are 2, 2, 3, 1, 1, 1, and 1. Add 1 to each exponent, giving 3, 3, 4, 2, 2, 2, and 2. Now multiply that list to get the number of divisors of the original number 76576500: 3 * 3 * 4 * 2 * 2 * 2 * 2 = 576. Here's the function:
def numdiv(n):
fs = factors(n)
f = fs.pop(0); d = 1; x = 2
while fs:
if f == fs[0]:
x += 1
else:
d *= x; x = 2
f = fs.pop(0)
return d * x
You can see these functions at work at http://codepad.org/4j8qp60u, and learn more about how they work at my blog. I'll leave it to you to work out the solution to Problem 12.

Categories

Resources