Infinite while loop in Python (finding prime number and GCD) - python

I am currently trapped by a infinite loop in my program and I really don't know what is the fault in it.
Here is my code:
from reference import brute_prime, euclid_gcd, extended_euclid
def rsa(min_p, min_q, min_e):
p = brute_prime(min_p)
q = brute_prime(min_q)
n = p * q
phi = (p - 1) * (q - 1)
e_prime = brute_prime(min_e)
while euclid_gcd(e_prime, phi) != 1:
e_prime = brute_prime(min_e)
print(e_prime)
e_prime += 1
return e_prime
#d = extended_euclid(e_prime, phi)
#tup1 = (d, e_prime, n)
#return tup1
My aim here is to use brute_prime and euclid_gcd to find e, by iteratively finding the next smallest prime number e_prime using brute_prime, and testing whether gcd(e′,ϕ)=1. If successful, terminate, if not, increment e_prime and continue.
Note that these functions that I called are all imported and there is nothing wrong in the function. What is wrong?
EDIT:
When trying to see the result of each iteration I tried something like this
print(rsa(11, 13, 3))
And the loop gives me 3 every single time.
EDIT:
This is brute_prime
def brute_prime(number):
#Making sure that the input from number will be type int
#setting two convenient limits for future use in the loop
number = int(number)
point_begin = 2
point_end = int((number**0.5)) + 1
#Two specific exceptions in the function that will execute and ignores
#later commands so that it is a tiny bit more efficient...
if number == 2:
return 2
elif number == 1:
return 1
while True:
condition = True
for i in range(point_begin, point_end):
if number % i == 0:
condition = False
break
if condition:
return number
else:
number += 1
EDIT:
This is Euclid_gcd
def euclid_gcd(num1, num2):
while num2:
num1, num2 = num2, num1 % num2
return int(num1)

Your while loop in RSA function looks buggy as min_e is not being updated, so same value is used in each iteration thus the loop is stuck, check your logic.
or use this:
while euclid_gcd(e_prime, phi) != 1:
e_prime = brute_prime(min_e)
min_e = e_prime + 1 # check for next prime-number co-prime to phi
Also note, 1 is not prime. For 1 as input, brute_prime should return 2.

Perhaps unrelated, but why not do something like
e_prime = brute_prime(min_e)
#This loop will not calculate and return me e_prime.
#Instead it just keeps running and exits later with nothing.
while euclid_gcd(e_prime, phi) != 1:
e_prime = brute_prime(min_e)
e_prime += 1
return e_prime

Related

Problems of defining a factorial function in python

I'm recently starting to learn coding in Python, this is the code that I tried to define a function that helps me to find the factorial of a number. Yet, this chunk of code always returns me the double of its factorial.
def factorial(x):
empty = None
try:
adj_x = int(x)
except:
print("Invalid Input")
if adj_x < 0:
print("Invalid Input")
elif adj_x == 0:
print(0)
else:
l_adj_x = adj_x - 1 # if input == 4, this is 3
r = range(1, l_adj_x) # 1, 2, 3
for k in r:
n = adj_x - k # 4-1 = 3, 4-2 = 2, 4-3 = 1
if empty is None:
empty = n
else:
empty = empty * n
n_adj_x = adj_x * empty * n
print(n_adj_x)
I realized that it is the problem of the n in this line:
n_adj_x = adj_x * empty * n
Based on my own understanding, the last n in the for-loop should be 1 (I took 4 as an example of my input and stated all the possible outcomes of the loop in the comments next to each line of code) , if so, why does it appear to be the double of the correct answer (when I include n in n_adj_x = adj_x * empty * n) since the n should equal to 1?
If what you are trying to get is the factorial here are some
examples:
Example 1
n = 10
factorial = 1
for i in range(1,n+1):
factorial *= i
print(factorial)
Example 2 <-- worst option
Slowest option and requires the most additional memory.
def fact(x):
if x <= 1:
return 1
return x * fact(x - 1)
print(fact(10))
Example 3 <-- Best option
import math
print(math.factorial(10))
This is the python libs built in function and probably performs better than my simple loop, however I have not tested it.

Factors of a number using Python recursive function

I've got an assignment which requires me to use a Python recursive function to output the factors of a user inputted number in the form of below:
Enter an integer: 6 <-- user input
The factors of 6 are:
1
2
3
6
I feel like a bit lost now and have tried doing everything myself for the past 2 hours but simply cannot get there. I'd rather be pushed in the right direction if possible than shown where my code needs to be changed as I'd like to learn
Below is my code:
def NumFactors(x):
for i in range(1, x + 1):
if x == 1:
return 1
if x % i == 0:
return i
return NumFactors(x-1)
x = int(input('Enter an integer: '))
print('The factors of', x, 'are: ', NumFactors(x))
In your code the problem is the for loop inside the method. The loop starts from one and goes to the first if condition and everything terminates there. That is why it only prints 1 as the output this is a slightly modified version of your own code. This should help. If you have any queries feel free to ask.
def factors(x):
if x == 1:
print(1 ,end =" ")
elif num % x == 0:
factors(x-1)
print(x, end =" ")
else:
factors(x-1)
x = num = int(input('Enter an integer: '))
print('The factors of', x, 'are: ',end =" ")
factors(x)
Since this question is almost 3 years old, I'll just give the answer rather than the requested push in the right direction:
def factors (x,c=1):
if c == x: return x
else:
if x%c == 0: print(c)
return factors(x,c+1)
Your recursion is passing down x-1 which will not give you the right value. For example: the number of factors in 6 cannot be obtained from the number of factors in 5.
I'm assuming that you are not looking for the number of prime factors but only the factors that correspond to the multiplication of two numbers.
This would not normally require recursion so you can decide on any F(n) = F(n-1) pattern. For example, you could use the current factor as a starting point for finding the next one:
def NumFactors(N,F=1):
count = 1 if N%F == 0 else 0
if F == N : return count
return count + NumFactors(N,F+1)
You could also optimize this to count two factors at a time up to the square root of N and greatly reduce the number of recursions:
def NumFactors(N,F=1):
count = 1 if N%F == 0 else 0
if N != F : count = count * 2
if F*F >= N : return count
return count + NumFactors(N,F+1)

Why does this Python code not work?

Please help, I cannot figure out why this code does not work. I think the first loop runs forever but I don't know why!
def NTN():
list1 = []
count = 0
number = 0
Start = input('Type Start Number')
while number != Start:
count = count + 1
number = number + count
Stop = input('Type Stop Number')
while number != Stop:
count = count + 1
number = number + count
if number != Stop:
(list1).append(number)
return (list1)
print(NTN())
You are increasing number by increasing amounts in every iteration. Here's an idea of how it is increasing. Assume Start = 4
After 1 loop, count = 1 and number = 1, increase of 1
After 2 loops, count = 2 and number = 3, increase of 2
After 3 loops, count = 3 and number = 6, increase of 3
Since number is never really equal to 4, the loop never ends. What you need probably is while number <= Start. That would terminate the loop after 3 iterations when number is past 4.
change "number != Start" and "number != Stop" to "number < Start" and "number < Stop" in all places, and it should work.
What went wrong: if Start is 2, then in the first iteration of the while loop, count becomes 0+1=1 and number becomes 0+1=1; in the second iteration, count becomes 1+1=2 and number becomes 1+2=3, which bypasses 2. Since your while loop only ends when number is equal to Start, it never ends.
A couple of side-points:
By convention Python variable and function names are lower-case.
input() returns a string; if you want a number you have to convert it ie with int() or float(). (Note: if you are using Python 2.x input() calls eval() which is really awful design - you should be using int(raw_input()) instead.)
so,
# This code assumes Python 3.x
from math import ceil, sqrt
def get_int(prompt):
"""
Prompt until an integer value is entered
"""
while True:
try:
return int(input(prompt))
except ValueError:
print("Please enter an integer!")
def tri(n):
"""
Return triangular number n,
ie the sum of (1 + 2 + ... + n)
"""
# using Gaussian sum
return n * (n + 1) // 2
def reverse_tri(t):
"""
For positive integer t,
return the least positive integer n
such that t <= tri(n)
"""
# derived by quadratic formula from
# n * (n + 1) // 2 >= t
return int(ceil(((sqrt(8 * t + 1) - 1) / 2)))
def ntn(start, stop):
"""
Return a list of triangular numbers
such that start <= tri < stop
"""
a = reverse_tri(start)
b = reverse_tri(stop)
return [tri(n) for n in range(a, b)]
def main():
start = get_int('Enter a start number: ')
stop = get_int('Enter a stop number: ')
lst = ntn(start, stop + 1) # include stop number in output
print(lst)
if __name__ == "__main__":
main()

While loop creating

I am writing a program in Python that defines a function that takes a single argument. The function has to be a while loop the returns the largest power of 16 that it is equal to. However, I am not sure how to write the while loop.
Python Docs
while True:
n = input("Please enter 'hello':")
if n.strip() == 'hello':
break
so, in layman's terms
while <condition>:
...
I couldn't completely understand your question but here's how to do a while loop to get the x to the 16th power of an input:
def loop_function(x):
y = 1
start = x
while y != 16:
result = start * x
start = result
y += 1
return result
print loop_function(3)
The above code will return the answer to 3^16 which is 43046721
You can even make this a broader function two arguements
def loop_function(x, y):
z = 1
start = x
while z != z:
result = start * x
start = result
z += 1
return result
print loop_function(3, 2)
The above code will return 9 i.e 3^2

How can I reimplement this recursive function?

So I'm trying to solve a puzzle and I came across this code. I can't figure out what the output would be and any attempts to run it result in a "reached the maximum amount of recursion" error. Sorry in advance for the goofy variable names.
How can I modify this to achieve the same output, without the recursion error? The initial numbers I'm passing are 13379446(arg 1) and 5(arg 2).
import sys
num1 = int(sys.argv[1])
num2 = int(sys.argv[2])
def doot(num1, num2):
print num1
print num2
doritos = 0
if num2 > num1:
pass
else:
if num2 == 0:
print "if"
doritos = 1
else:
if num2 == num1:
doritos = 1
else:
wew = doot(num1 - 1, num2 - 1)
doritos = wew
wew = doot(num1 -1, num2)
doritos = doritos + wew
print doritos
Let me get you started. I'm assuming that doritos is supposed to be the return value, that is, that the code should say return dortitos instead of print doritos. Also, I'm completely ignoring the line print if.
Now what do we know? Looking at the code we see that
doot(x,y) = 0 if y > x
doot(x,0) = 1
doot(x,x) = 1 and
doot(x,y) = doot(x-1,y-1) + doot(x-1,y) otherwise
So we want to figure out the value of doot(x+h,x) where h > 0. Start with the simplest case, h=1. We already know that doot(1,0)=1, so
doot(2,1) = doot(1,0)+doot(1,1) = 1+1 = 2
doot(3,2) = doot(2,1)+doot(2,2) = 2+1 = 3
and now it's easy to guess that
doot(x+1,x)=x+1 for all x>= 0.
t's also easy to prove this by induction, if you're so inclined.
So now, work out some examples when h=2, and figure out the formula for doot(x+2,x). Then figure out the formula for doot(x+3,x) and so on, until you're ready to guess the the formula for doot(x+h,x)
Okay, I overhauled your code to use a dictionary (values) and a queue.
import sys
num1 = int(raw_input("num1: "))
num2 = int(raw_input("num2: "))
def doot(num1, num2):
print num1
print num2
doritos = 0
n1 = num1
n2 = num2
values = {}
queue = [(num1,num2)]
while queue:
num1,num2 = queue.pop()
#print queue
#print values
if (num1,num2) not in values:
if num1 >= num2:
if num2 == 0:
#print "if"
#doritos = 1
values[(num1,num2)] = 1
else:
if num2 == num1:
#doritos = 1
values[(num1,num2)] = 1
else:
#wew = doot(num1 - 1, num2 - 1)
#doritos = wew
#wew = doot(num1 -1, num2)
#doritos = doritos + wew
if (num1-1,num2-1) in values and (num1-1,num2) in values:
values[(num1,num2)] = values[(num1-1,num2-1)] + values[(num1-1,num2)]
else:
queue.append((num1,num2))
if (num1-1,num2) not in values:
queue.append((num1-1,num2))
if (num1-1,num2-1) not in values:
queue.append((num1-1,num2-1))
#print values
doritos = values[(n1,n2)]
print doritos
return doritos
doot(num1,num2)
In essence, I use the queue to keep track of the sums I don't have yet. If both of the descendants of (num1,num2) are in the dictionary, then I put it in the dictionary with the sum of their values. Otherwise, I put either or both descendant that's not in the dictionary on the queue along with itself. The other times that I don't put (num1,num2) back on the queue are when num1 == num2 or num2 == 0, in which cases I put them in the dictionary with value 1. At the end, I return the value in the dictionary that corresponds to the original inputted numbers.
Now, a word of caution: this code is horribly inefficient. I just had to reboot my computer because I tried the inputs you gave in the question, and it gobbled up all of the available RAM. So, you should instead consider what exactly is being done with the recursion, and figure out how to work forwards from the base cases instead of backwards from the input. That task, I will leave to you.
Your code is a recursive implementation of a combination function, which calculates the number of combinations of k distinct elements that can be drawn from a set of n elements.
A tidied up version of your function would look like this (note I have removed all the print statements and ensured that the function returns something - otherwise it won't work at all).
def doot(n, k):
if n < k:
return 0
if k == 0 or n == k:
return 1
return doot(n - 1, k - 1) + doot(n - 1, k)
This works fine for small values of n and k. A faster version that doesn't rely on recursion uses factorials, as shown in this answer.
import math
def nCr(n, r):
f = math.factorial
return f(n) / f(r) / f(n - r)
However, calculating the factorial of 13379446 still takes a long time and may not be accurate because the result is so huge. My system hangs when I try it. The other answer to the same question appears to work better.

Categories

Resources