Function to calculate RSA crashes program after first print - python-3.x

Function stops running after first print
When I run the following and input p=7, q=11, it runs fine all the way through and prints both keys. However, if I chose slightly larger numbers suck as p=67, q=83 it prints the value of “e” (line 13) and then stops running and exits the program that this function is within entirely when it should print the keys and return to a home menu. Any ideas why this might be?
import random
import math
def create_key_set():
p = int(input('Insert prime number for value of p: '))
q = int(input('Insert new prime number for value of q: '))
N = p * q
y = (p-1) * (q-1)
while True:
cop = random.randint(2, y-1)
gcd = math.gcd(cop, y)
if gcd == 1:
break
e = cop
print(e)
pubkey = [e, N]
while True:
d = random.randint(1, 150)
g, x = divmod((e*d), y)
if x == 1:
break
print(d)
privkey = [d, N]
print('Public Key is: ', pubkey)
print('Private Key is: ', privkey)
I’m don’t think it’s a computing issue because I tried it with cloud computing and it did the same thing. I definitely could be wrong though. Also it may be written terribly. This is the first time I’ve written python in a few years and I pretty much pieced it together from the internet. I’ve got no idea what’s wrong so any help on the issue and general tips in general would be appreciated.

The loop to find d (the second loop) is very likely to be an infinite loop. There's really no reason to use randint in that loop at all, and no reason to restrict randint to be between 1 and 150. Take out that entire loop and throw it away, and replace it with this one line: d = pow(e, -1, y), so you're code looks something like
def create_key_set():
p = int(input('Insert prime number for value of p: '))
q = int(input('Insert new prime number for value of q: '))
N = p * q
y = (p - 1) * (q - 1)
while True:
cop = random.randint(2, y - 1)
gcd = math.gcd(cop, y)
if gcd == 1:
break
e = cop
print(e)
pubkey = [e, N]
d = pow(e, -1, y)
print(d)
privkey = [d, N]
print('Public Key is: ', pubkey)
print('Private Key is: ', privkey)

Related

Values in list are sometimes switching and i dont know why

I'm programming a length conversion calculator in python. I will convert the input to a sheet. Then I compare the input (as a set) with the dictionary and pull the appropriate values. My problem is that sometimes the values in the list are stored in the opposite order than they should be. For example mm -> m should always be stored as [0, 3] in the list but sometimes it gets switched [3, 0] and I don't know why. I tried the import -> Orderedlist method. Still the same problem. Here is my code.
def prevod_delky():
x = None #vstup format list
y = None
z1 = {'mm':0, 'cm':1, 'dm':2, 'm':3}
x = input('Enter the value and conversion units. E.g. mm -> cm. \n')
x = x.lower().split(' ', 2)
try:
x[0].replace('.', '', 1).isdigit()
x[0] = float(x[0])
except:
print('Enter only digits!')
prevod_delky()
try:
y = {k: z1[k] for k in z1.keys() & set(x)}
y = list(y.values())
except:
print('Something went wrong!')
prevod_delky()
try:
a = abs(int(y[0] - y[1]))
if y[0] > y[1]:
for y in range(0, a):
x[0] = x[0] * 10
else:
for y in range(0, a):
x[0] = x[0] / 10
except:
print('Something went wrong')
finally:
print('The resulting length is {} {}'.format(x[0], x[2]))
prevod_delky()
I tried the import -> Orderedlist method.
I checked Python version (using 3.8.1)

name 'count' is not defined in python

I have this code in python and I am trying to make a counter for the iteration of the binary search (yeah I know it is incomplete...), but I am stuck with the variable inside the function, when i try to print the variable count I get this error
name 'count' is not defined in python
can someone explain why i get this error?
import csv
def binarySearch(arr, l, r, x):
count=0
while l <= r:
mid = int(l + (r - l) / 2)
# Check if x is present at mid
if arr[mid] == x:
return mid
# If x is greater, ignore left half
elif arr[mid] < x:
l = mid + 1
# If x is smaller, ignore right half
else:
r = mid - 1
# If we reach here, then the element
# was not present
return -1
with open('bl_printed_music_500.csv', newline='', encoding="utf-8-sig") as csvfile:
reader = csv.DictReader(csvfile)
arr=[]
for row in reader:
if row ["Publication date (standardised)"] != "":
arr.append(int(row["Publication date (standardised)"])) #create list for searching
list.sort(arr) #list must be sorted to work
#print (arr)
x = 1850 #year to search
# Function call
result = binarySearch(arr, 0, len(arr) - 1, x)
found = False
if result != -1:
found = True
print(found)
print(count)
I think it's because you defined count in binarySearch but try to use it outside of the method. Try using a global variable (define it outside of binarySearch), it should work.
You can return count as well.
For example:
def myFunc():
x = 5
y = 10
return x,y
a, b = myFunc()
print(a)
print(b)
This will be:
5
10
Note that, I could have written x, y = myFunc(). These x and y are not the same as the ones inside myFunc(). The latter are local to the function.
In your code, you can return your local count variable:
return mid, count #(A)
return -1, count #(A)
And get its value by:
result, count = binarySearch(arr, 0, len(arr)-1, x) #(B)
Again, these two count variables, (A) and (B) are different variables with different scopes.
See, for instance:
https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value
Alternatively, if a global variable, as suggested in the other answer, suits you best, you can see an example of its usage in the link.

Why is my python function not working properly when I call it recursively?

I'm doing a question from a previous Waterloo ccc competition (https://cemc.uwaterloo.ca/contests/computing/2020/ccc/juniorEF.pdf problem J5)
and my code isn't working the way I expected
Here's the sample input I'm using:
3
4
3 10 8 14
1 11 12 12
6 2 3 9
Here's my code so far
y_size = int(input())
x_size = int(input())
mat = []
"ok".split()
for i in range(y_size):
row = input().split()
mat.append(row)
pos_list = [[0, 0]]
current_num = int(mat[0][0])
a = 0
def canEscape():
global a
global mat
global pos_list
global current_num
end = y_size * x_size
if y_size -1 * x_size -1 == current_num:
return True
for i in range(y_size):
print("______")
for j in range(x_size):
v = (i + 1) * (j + 1)
print(v)
print(current_num)
if v == current_num:
print("ok")
if v == end:
print("ok")
a += 1
current_num = mat[i][j]
pos_list.append([i, j])
canEscape()
pos_list.pop(-1)
a -= 1
current_num = mat[pos_list[a][0]][pos_list[a][1]]
canEscape()
The problem I'm having is that I expect if v == current_num: to be true when I call it again. Both current_num and v are equal to 8 but the code seems to carry on with the for-in loop and break, without entering the if statement. I've made the output print v followed by current_num for every iteration of the for loop to try and figure out the problem but it seems that both variables == 8 so I really don't know what I did wrong. Did I make a silly mistake or did I structure my whole program wrong?
I'm having trouble following what your program is doing at all. This problem involves integer factoring, and I do not see where you're factoring integers. You definitely are not understanding that aspect of the problem.
When you calculate what cells you can go to you look at the value of your current cell. Lets say it is 6. 6 has the factors 1, 2, 3, and 6 because all of those numbers can be multiplied by another number to equal 6. So, you can go to the cells (1, 6), (6, 1), (2, 3), and (3, 2), because those are the pairs of numbers that can be multiplied together to equal 6.
Also, you never convert the lines of input into integers. When you append to the matrix, you are appending a list of strings that happen to be numbers. You must convert those into integers.
Anyways, this program will solve the problem. I copy and pasted the factoring algorithm from other threads:
n_rows = int(input())
n_cols = int(input())
mat = []
for i in range(n_rows):
mat.append(list(map(lambda x: int(x), input().split()))) # Convert input strings to integers.
def reduce(f, l):
# This is just needed for the factoring function
# It's not relevant to the problem
r = None
for e in l:
if r is None:
r = e
else:
r = f(r, e)
return r
def factors(n):
# An efficient function for calculating factors.
return set(reduce(list.__add__,
([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))
def get_pairs(items):
for i in range(len(items) // 2):
yield (items[i],items[len(items) - 1 - i]) # use yield to save memory
if(len(items) % 2 != 0): # This is for square numbers.
n = items[len(items) // 2]
yield (n,n)
checked_numbers = set()
def isPath(r=1, c=1):
# check if the testing row or column is to large.
if r > n_rows or c > n_cols:
return False
y = r - 1
x = c - 1
n = mat[y][x]
# If we've already checked a number with a certain value we dont need to check it again.
if n in checked_numbers:
return False
checked_numbers.add(n)
# Check if we've reached the exit.
if(r == n_rows and c == n_cols):
return True
# Calculate the factors of the number, and then find all valid pairs with those factors.
pairs = get_pairs(sorted(list(factors(n))))
# Remember to check each pair with both combinations of every pair of factors.
# If any of the pairs lead to the exit then we return true.
return any([isPath(pair[0], pair[1]) or isPath(pair[1], pair[0]) for pair in pairs])
if isPath():
print("yes");
else:
print("no");
This works and it is fast. However, it if you are limited on memory and/or have a large data input size your program could easily run out of memory. I think it is likely that this will happen with some of the testing inputs but I'm not sure.. It is surely possible to write this program in a way that would use a fraction of the memory, perhaps by converting the factors function to a function that uses iterators, as well as converting the get_pairs function to somehow iterate as well.
I would imagine that this solution solves most of the testing inputs they have but will not solve the ones towards the end, because they will be very large and it will run out of memory.

My two approaches to solve Fibonacci Last Digit Problem on Python

I am a newbie here. If I do something wrongly, please show me tolerance.
I tried to solve this problem:
Problem_Picture_1
Problem_Picture_2
My first solution didn't work:
# Uses python3
import sys
# Uses python3
def get_fibonacci_last_digit(n):
fib = [0, 1]
if n <= 1:
return n
for i in range(2, n):
current = (fib[i-1] + fib[i-2]) % 10
fib.append(current)
return fib[-1]
n = int(input())
if __name__ == '__main__':
input = sys.stdin.read()
n = int(input)
print(get_fibonacci_last_digit(n))
But my second solution worked:
# Uses python3
def calc_fib(n):
fib = [0, 1]
if n <= 1:
return n
for i in range(2, n+1):
current = (fib[i-1] + fib[i-2]) % 10
fib.append(current)
return fib[-1]
n = int(input())
print(calc_fib(n))
What is the difference between these two approaches? Why didn't work my first solution? Please explain to me.
Edit:
When I worked my first approach, It's still running. It couldn't return a number
When I worked my first approach, It could return a number
The range(A, B) object iterates from A (inclusive) to B (exclusive). Eg.- range(2, 5) will return (2, 3, 4).
PS - Please use proper indentation while posting a question

Can any one help me with this one . I was trying to write a prog for finding 'LCM'. I want to equate these variable

Here c and d basically represent tables of respective number for variable a and b...i am trying to match the least common product from these table.Please help me figure it out
a=(input('your first no: '))
b=(input('your second no: '))
for i in range(1,100):
c=a*i
d=b*i
if (c==d):
print('lcm is')
Here is a program that will work. It will also calculate the LCM of more than two numbers.
from collections import Counter
from operator import mul
from functools import reduce
def primeFactors(n):
if not isinstance(n, int) or n < 1:
raise ValueError("must be positive integer")
factors = []
while n % 2 == 0:
factors.append(2)
n /= 2
i = 3
while n != 1:
while n % i == 0:
factors.append(i)
n /= i
i += 2
return factors
def get_lcm(numbers):
factorisations = [Counter(primeFactors(n)) for n in numbers]
primes = frozenset().union(*(set(x.keys()) for x in factorisations))
primes_to_max_powers = (p ** max(*(x.get(p,0) for x in factorisations))
for p in primes)
return reduce(mul, primes_to_max_powers, 1)
a = int(input('your first no: '))
b = int(input('your second no: '))
print('lcm is', get_lcm([a, b]))
Or you can do this instead but it might be a bit slower:
a = input('your first no: ')
b = input('your second no: ')
for i in range(max(a, b), a * b + 1):
if i % a == 0 and i % b == 0:
lcm = i
break
print('lcm is ', lcm)
Use the formula lcm(a,b) = a⋅b / gcd(a,b). Python has a gcd function in the standard library:
from fractions import gcd
def least_common_multiple(a, b):
return a * b / gcd(a, b)
Since Python 3.6, it's arguably preferable to use the gcd builtin from math:
try:
from math import gcd
except ImportError:
from fractions import gcd
def least_common_multiple(a, b):
return a * b / gcd(a, b)

Resources