Python function hangs for large numbers [duplicate] - python

This question already has an answer here:
Why is my function using Python time limited in input value magnatude?
(1 answer)
Closed 9 years ago.
I am trying to make a function that calculate the modular exponential MODEXP(a,e,p).
This function takes m and n as a parameters, where p is a prime number at most 2^m and e is 2^n and a is random number less than p.
Here is my code:
import random
def question_3(m,n):
list = []
i = 1
for i in range(2,2**m):
flag=True
for num in list:
if(i%num==0):
flag=False
if flag:
list.append(i)
p = choice(list)
a = randint(1,int(p)-1)
e = pow(2,n)
return pow(a, e, p)
question_3(5,5)
For m and n over 20, the code begins to hang. How do I prevent that?

If you just want to calculate
(modulus of a raised to the power e)modp
or something similar then
I would Highly recommend you this wiki article
In this case maximum number of iteration would be equal to number of bits in binary representation of variable e.

Related

Codility Test : Square Number [duplicate]

This question already has answers here:
Check if a number is a perfect square
(25 answers)
Closed 11 months ago.
I had a Codility Test, and the question asked me to create a code that listed numbers 1-1000, but at every square number, the program prints
"POWER" instead of the square number. It should look like this:
POWER
2
3
POWER
5
6
7
8
POWER
10
And so on...
I've been trying to solve this, but I can't think of any correct solutions, any help would be much appreciated.
for n in range(1,11):
print(n)
if n == n**2:
print("POWER")
elif n==22:
print("POWER")
elif n==3**2:
print("POWER")
This is the only thing I could think of, but I don't know how I could create a loop for this 1000 times, also the output didn't come out as I wanted it to.
My solution is: calculate sqrt of number, check if it is a whole number using built-in method is_integer() on float object:
import math
for i in range(1000):
if math.sqrt(i).is_integer():
print("POWER")
else:
print(i)
The important things you're missing are the math.sqrt and round functions, which make it very easy to figure out if a number is a perfect square (just check whether the sqrt of the number is round):
import math
for n in range(1,1001):
s = math.sqrt(n)
if s == round(s):
print("POWER")
else:
print(n)
If you weren't allowed to use those functions, another option (which would save you from having to do a guess-and-test iteration for each number) would be to build a set of square numbers within the range you care about and test each n for membership in that set:
squares = {n ** 2 for n in range(1, 32)}
for n in range(1,1001):
if n in squares:
print("POWER")
else:
print(n)

Create a function that computes how many proper fractions you can build with a given denominator using Python [duplicate]

This question already has answers here:
Finding the number of reduced fractions
(3 answers)
Closed 2 years ago.
Objective: Build a function that computes how many proper fractions you can build with a given denominator
Problem: Codewars is a platform used for the code submission. Upon submission it will not accept my code because it is not efficient even though I passed all test cases. Can someone please suggest me how could I optimize my code even more
Code:
from fractions import Fraction
def proper_fractions(n):
count = 0
for i in range(1,n):
fractionA = Fraction(i, n)
if fractionA.denominator == n:
count+=1
return count
Sample Tests:
Test.assert_equals(proper_fractions(1),0)
Test.assert_equals(proper_fractions(2),1)
Test.assert_equals(proper_fractions(5),4)
Test.assert_equals(proper_fractions(15),8)
Test.assert_equals(proper_fractions(25),20)
This should be 7 to 8 times faster:
from math import gcd
def fracCount(N): return sum(gcd(d,N)==1 for d in range(1,N))
For a given N, there will be a maximum of N-1 fractions : 1/N, 2/N, 3/N ... (N-1)/N. The ones that are not proper fractions are when the numerator and denominator can be divided by a common divider (which we can detect with gcd).
output:
print(fracCount(1)) # 0
print(fracCount(2)) # 1
print(fracCount(5)) # 4
print(fracCount(15)) # 8
print(fracCount(25)) # 20
[EDIT]
For an even faster solution, you can obtain the "improper" numerators by finding all multiples of the prime factors of N. You need a function that returns prime factors such as the one below. Subtract the number of these improper numerators from N-1 to get the count of proper fraction
def primeDivs(N):
p = 2
while N>=p*p:
if N%p == 0: yield p
while N%p==0: N //= p
p += 1 + (p&1)
if N>1 : yield N
def fracCount(N):
return N-1-len({f for p in primeDivs(N) for f in range(p,N,p)})
This one is roughly 100 times faster than proper_fractions()
[EDIT2] Using Euler's totient function is even faster (on large values of N):
def totient(N):
tot = N
for p in primeDivs(N):
tot -= tot//p
return tot
def properFractions(N): return 0 if N<2 else totient(N)
It's more than 3000 times faster than proper_fractions for N = 10000.

How to determine the existence of a d-redigit multiple of N? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have the following problem:
I am given 2 natural positive numbers: d and N.
I need to find the length of the minimum d-redigit that is a multiple of N.
A natural number x is a d-redigit if x is a sequence of d's.
Example: 111111 is a 1-redigit.
There may be no d-redigit multiple of N.
I know how to solve the problem when I know that a d-redigit that is multiple of N exists. However, my question is: How can I determine if this d-redigit, multiple of N, exists?
Note: The programming language for this implementation doesn't really matter, it can be pseudo code, GCL preferably.
I have tried the following implementation in Python:
def proyect_a(n:int, d:int):
if n == 0 or d == 0:
return ''
i = 1
red = d
while i < 11 and red%n != 0:
red = 10*red + d
i+=1
if i < 11:
return len(str(red))
else:
return '*'
The previous algorithm is a brute-force partial solution, since it can't really tell the length of the minimum d-redigit for all cases. As you can see, the cycle repeats 10 times max, given that I really don't know how to check if a d-redigit multiple of N exists.
First of all, since you're only concerned about divisibility by n, there's no need to use huge integers. Just compute the value of repdigit modulo n at each step. For any value of repdigit, there are only n possible values of repdigit % n, so if you don't find a multiple of n after n iterations, you can be sure that no solution exists.
But you can do a lot better by looking for repeating cycles in the calculated values. The simplest approach would be to store each successive value of repdigit. If a value occurs twice, then that means you've entered a repeating cycle and there is no solution. But there's no need to store every value of repdigit. Each iteration of the loop is equivalent to calculating the next output of a linear congruential generator with a=10, c=d, and m=n. If you start with an initial value of zero, the output sequence will settle into a repeating cycle after at most 3 iterations.
With a bit of mathematical reasoning, you could speed up the calculations even more. What you're essentially calculating is the number of iterations that it takes for an LCG seeded with a value of zero to output zero a second time (using parameters a,c,m = 10,d,n).
For example, this LCG will produce a maximal length sequence when n and d are coprime and n is a power of 3, in which case min_repdigit_multiple(n,d) will be equal to n. There are probably other short cuts you could take.
def min_repdigit_multiple(n:int, d:int):
#
# Returns the length of the smallest repdigit number divisible by n
# i.e. the smallest value of x such that ((10**x-1)*d//9) % n == 0
# If no solution exists, returns -1 instead
#
assert 0 < d <= 9, "d must be a single non-zero digit"
#
# Check for a maximal length LCG sequence
from math import gcd
if gcd(n,d) == 1:
n0 = n
while n0 % 3 == 0:
n0 //= 3
if n0 == 1:
return n
#
i = 1
repdigit = 0
seen = set()
while i <= n:
repdigit = (10 * repdigit + d) % n
if repdigit in seen:
# We've been here before, so there is no solution
return -1
if repdigit == 0:
# Success: repdigit is divisible by n
return i
# There's no point in storing more
# than the first few values of repdigit
if i < 4:
seen.add(repdigit)
i += 1
return -1 # Searched all possible values without finding a solution

compare float number in python [duplicate]

This question already has answers here:
What is the best way to compare floats for almost-equality in Python?
(18 answers)
Closed 3 years ago.
Greeting All,
I want to compare float number that but I don't wanna round the number
here is a simple example:
p = 15.0060732
n = 15.00637396
if p == n:
print('=')
if p > n:
print('>')
if p < n:
print('<')
I want p < n , is there any method to hlpe me do that.
* Note: I have a big table that represent these value but it's random so i can't determin the floating point for all table.
any help will be appreciated
Python compares floating-point numbers. Because of the precision, you should use the isclose method of the math module.
If the difference between the two numbers is less than 1e-9, then the two floating point numbers are considered equal.
Math.isclose(a, b, rel_tol=1e-9)
example:
import math
p = 15.0060732
n = 15.00637396
print(math.isclose(1.0, 1.0000000001))
print(math.isclose(1.0, 1.0000000001, rel_tol=1e-10))
print(math.isclose(p, n))
print(math.isclose(p, n, rel_tol=1e-2))
result:
True
False
False
True

Random number that is divisible by N [duplicate]

This question already has answers here:
Python: Generate random number between x and y which is a multiple of 5 [duplicate]
(4 answers)
Closed 3 years ago.
I want to generate a random number from range [a,b] that is dividsible by N (4 in my case).
I have the solution, but is there a better (more elegant) way to do it?
result = random.randint(a, b)
result = math.ceil(result / 4) * 4
Solutions from here:
Python: Generate random number between x and y which is a multiple of 5
doesn't answer my question since I'll have to implement something like:
random.randint(a, b) * 4;
I'll have to divide original range by 4 and it's less readable then my original solution
A generic solution and an example
import random
def divisible_random(a,b,n):
if b-a < n:
raise Exception('{} is too big'.format(n))
result = random.randint(a, b)
while result % n != 0:
result = random.randint(a, b)
return result
# get a random int in the range 2 - 12, the number is divisible by 3
print(divisible_random(2,12,3))
The first thing coming to my mind is creating a list of all the possible choices using range in the given interval, followed by randomly choosing one value using choice.
So, in this case, for a given a and b,
random.choice(range(a + 4 - (a%4), b, 4))
If a is a perfect multiple of 4, then
random.choice(range(a, b, 4))
Would give you the required random number.
So, in a single generic function, (as suggested in comments)
def get_num(a, b, x):
if not a % x:
return random.choice(range(a, b, x))
else:
return random.choice(range(a + x - (a%x), b, x))
where x is the number whose multiples are required.
As the others have pointed out, your solution might produce out of range results, e.g. math.ceil(15 / 4) * 4 == 16. Also, be aware that the produced distribution might be very far from uniform. For example, if a == 0 and b == 4, the generated number will be 4 in 80% of the cases.
Aside from that, it seems good to me, but in Python, you can also just use the integer division operator (actually floor division, so it's not equivalent to your examlpe):
result = random.randint(a, b)
result = result // 4 * 4
But a more general albeit less efficient method of generating uniform random numbers with specific constraints (while also keeping the uniform distribution) is generating them in a loop until you find a good one:
result = 1
while result % 4 != 0:
result = random.randint(a, b)
Use random.randrange with a step size of n, using a+n-(a%n) as start if a is non-divisible by n, else use a as start
import random
def rand_n(a, b,n):
#If n is bigger than range, return -1
if n > b-a:
return -1
#If a is divisible by n, use a as a start, using n as step size
if a%n == 0:
return random.randrange(a,b,n)
# If a is not divisible by n, use a+n-(a%n) as a start, using n as step size
else:
return random.randrange(a+n-(a%n),b, n)

Categories