Using prime numbers to generate a random password - python

I'm doing a college project which started off with printing out all the prime numbers between two given inputs. I was later told that it had to be somewhat relevant to my course, Network Management, so I wanted to add a password generator onto the end of my script(for network security)
I have all the code written out but I have a problem with it not being able to use a random prime number in the list I have printed out. It only uses the last number printed and I understand why but is there anyway I can make it so that does use a random prime number or will I have to store the numbers somewhere?
#A program to count the prime numbers from a given start to a given end
#importing math function
import math
import os, random, string
#Input the number to start counting from
Starting_number = input("Enter the starting number: ")
#Input the number to end the count on.
Ending_number = input("Enter the number you want to count up to: ")
#if Starting_number is less than 0 it will print out a suitable message.
if Starting_number < 0:
print 'Invalid entry, please enter a positiv number. \nWill count from ',Starting_number, 'to 0 and begin prime number count to',Ending_number, '.'
#If Ending_number is less than or equals to 0 then it will print out a suitable message.
if Ending_number <= 0:
print 'Invalid entry on last input \nPlease enter two positive numbers for the count to work.'
#Starting loop as long as the current count is between Starting_number and Ending_number
for num in range(Starting_number, Ending_number):
#
if all(num%i !=0 for i in range(2,num)):
print num
if num >= 1 and num <= 100:
length = 4
chars = string.ascii_letters + string.digits + '!##$%^&*()'
random.seed = (os.urandom(1024))
print ''.join(random.choice(chars) for i in range(length))
if num >= 101 and num <= 200:
length = (Ending_number / Starting_number) * 5 + 11
if length >= num:
length = num / 100
chars = string.ascii_letters + string.digits + '!##$%^&*()'
random.seed = (os.urandom(1024))
print ''.join(random.choice(chars) for i in range(length))

As you detect prime numbers add them to a list.
Instead of just
print num
add it to a list like so:
primes.append(num)
then you can select a random item from your 'primes' list:
from random import choice
print choice(primes)

I really wanted to add this as a comment but I do not have enough credits to add a comment. For password generator, you do not want it to be a prime number. You should just randomly choose a number. If you have a 32 bit number, you have more entropy if the number is randomly in the full 32-bit space. If you limit it to only prime numbers, you have considerably reduced the space. Not directly related to what you are asking but it may be useful to know.

Related

Error with my random number generation code

My code it generates a random number it checks if it is in the list if it is it generates another random number and then it checks if it is equal or not and shows the result and repeats the process. But when I start the code it generated the normal number but it repeats the numbers and it shouldn't repeat the number. What do I do?
from random import randint
import os
n = 0
numsort = 14564487
attempt = 0
numbers = []
while n < 100:
num = randint(10000000, 99999999)
if num in numbers:
num = randint(10000000, 99999999)
numbers.append(num)
attempt += 1
if num == numsort:
print(f'{num}' + '\033[32m' + ' Right number' + '\033[0m')
print(f'After {attempt} attempts it was')
break
if num != numsort:
print(f'{num}' + '\033[31m' + ' Wrong number' + '\033[0m')
print(f'Attempt # {attempt}')
os.system('clear')
The issue here is a simple one. The primary problem is with this code snippet:
num = randint(10000000, 99999999)
if num in numbers:
num = randint(10000000, 99999999)
numbers.append(num)
Translating this to English, we have:
Generate a random seven-digit integer
If the integer is in our list of numbers then regenerate it and add it to the list
The problem you have here is that you have no guarantee that the regenerated number won't also be in the list. The chance of this happening will grow as the list grows. And, since your loop variable is never updated, this list will grow infinitely.
To fix this problem, you have two possible solutions. For small lists, you can continue on with your strategy of regenerating numbers and replace the if with a while:
num = randint(1000000, 9999999)
while num in numbers:
num = randint(1000000, 999999999)
numbers.append(num)
Note that this will only work while the desired size of your list is much smaller than the range of possible values being generated. As you fill up the list, the chance of collisions between the range of possible values and actual values will increase, causing the while loop to run longer.
Alternatively, you can use sample to choose your values, which would replace the entire loop:
numbers = random.sample(range(1000000, 10000000), n)
Note here that the use of range means that this is actually just as space efficient as the previous solution and will guarantee unique values.

Cycling the digits of a 5 digit number in a function

I'm trying to solve this problem but I'm just stuck at the very end.
I need to make a function that cycles the 5 digit number around. So for example, the input is 12345 and then it should be 51234, 45123 etc. Then when it cycles it out, until it's at the beginning again which is 12345, it should print out the biggest number of all of the cycled ones.
def number_cycle(number):
if number >= 99999 or number < 9999:#this is for limiting the number to 5 digits
print('Error,number isnt in 5 digit format')
else:
e = number%10 #5th digit
d = int(((number-e)/10)%10)#4th digit
c = int(((((number - e)/10)-d)/10)%10)#3rd digit
b = int(((((((number - e)/10)-d)/10)-c)/10)%10)#2nd digit
a = int(((((((((number - e)/10)-d)/10)-c)/10)-b)/10)%10)#1st digit
print(e,a,b,c,d)
print(d,e,a,b,c)
print(c,d,e,a,b)
print(b,c,d,e,a)
print(a,b,c,d,e)
number = eval(input('Input number:'))
I can't figure out how to get the biggest number out of all these.
Can you help?
You can try this solution:
def get_largest(number):
num_str = str(number)
num_len = len(num_str)
if num_len != 5:
print(f"Error: {number} is not a 5 digit number")
return
largest = 0
for i in range(num_len):
cycled_number = int(num_str[i:] + num_str[:i])
print(cycled_number)
if cycled_number > largest:
largest = cycled_number
print("Largest: ", largest)
number = int(input("Input number: "))
get_largest(number)
It will basically convert your 5 digit number to a string using a for loop, and then rotate the string, compare the rotated numbers and print the largest one.
Note:
In your original code snippet I'd suggest not to use the built-in eval method as it can be quite dangerous if you don't know what you are doing so avoid it as much as you can except you really have no other way to deal with a problem. More here:
https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html
https://medium.com/swlh/hacking-python-applications-5d4cd541b3f1

Python: Find Prime Number Algorithm

Recently I was given a challenge to my coding skills by my teacher since he saw that I was already knowledgeable in what he was teaching. The question is as follows.
Create a program that prompts the user for 2 numbers. The program will then display all the prime numbers in between the two given numbers, including the given numbers. Note: You cannot assume the first input is bigger than the second input.
So I took this question and built a fairly simple algorithm and ran it and it worked. I opened it today to find out for some reason my output is occasionally wrong, for example when you input 8 and 29 I get 27. I am looking for HINTS as to what is wrong with my logic because I cannot for the life of me figure out what Im doing wrong. I dont want straight up fixes because I would like to learn as much from this and doing it as much as possible by myself.
numbers = [int(input("First Number")), int(input("Second Number"))]
numbers.sort()
numList = []
#Removing Even Numbers
for num in range(numbers[0],numbers[1] + 1):
if num % 2 != 0:
numList.append(num)
#Checking For Prime Numbers
for currNum in numList:
#Set Start number to divide
i = 2
while i < currNum:
#Checks if the currNum can be divisble by i and is a whole number
if currNum % i != 0:
i = i + 1
else :
numList.remove(currNum)
break
print(numList)
From what I have learned from testing this out it seems like 27 is never checked during my for loop or while loop even though it is in the numList array.
Never remove items form a list you are iterating over.
Instead create a new list:
numbers = [int(input("First Number")), int(input("Second Number"))]
numbers.sort()
primes = []
for num in range(numbers[0], numbers[1] + 1):
#Set Start number to divide
i = 2
while i < num:
#Checks if the currNum can be divisble by i and is a whole number
if num % i == 0:
break
i += 1
else:
primes.append(num)
print(primes)

How do I find the most and least guessed numbers in an array of random numbers in Python?

I just have to find the most and least guessed numbers in an array of random numbers in python. Here is my code by far:
import time
import random
random.seed()
def breakPIN(num):
end = 0
list = []
for i in range(0,9999):
list.append(random.randint(0,9999))
printNow(list)
if (num == 4):
end =9999
elif (num == 6):
end=999999
p2b=random.randint(0,9999)
time1=time.time()
num=random.randint(0,end)
while (num!=p2b):
num=random.randint(0,end)
list[num]=list[num]+1
time2=time.time()
lowest=list[i]
for i in range(0,len(list)):
if(lowest > list[i]):
lowest=list[i]
printNow(lowest)
highest=list[i]
for i in range(0,len(list)):
if(highest<list[i]):
highest=list[i]
printNow(highest)
return time2-time1
times=[]
for i in range(0,10):
times.append(breakPIN(6))
sum=0
for i in range(0,len(times)):
sum = sum + times[i]
printNow(sum/len(times))
printNow(times)
As you can tell I can already find the largest number as well as the smallest numbers guessed. Any pointers as to how I can find the most and least guessed numbers would be very much appreciated.
To find the most and the least guessed numbers you could use Counter:
import random
from collections import Counter
def most_least_guessed(elements):
counts = Counter(elements)
most_guessed, _ = counts.most_common(1)[0]
least_guessed, _ = counts.most_common()[-1]
return most_guessed, least_guessed
random.seed(42)
lst = []
for i in range(0, 9999):
lst.append(random.randint(0, 9999))
most, least = most_least_guessed(lst)
print(most, least)
Output
1106 9998
To determine the most and least guessed numbers you need to know how many times each number was guessed. Once you know how many times each one was guessed you can just find the min and max.
To record how many times each number was guessed you will need an array that is the same length as the count of available numbers.
This is called a histogram.

How can I display all numbers in range 0-N that are "super numbers"

The program asks the user for a number N.
The program is supposed to displays all numbers in range 0-N that are "super numbers".
Super number: is a number such that the sum of the factorials of its
digits equals the number.
Examples:
12 != 1! + 2! = 1 + 2 = 3 (it's not super)
145 = 1! + 4! + 5! = 1 + 24 + 120 (is super)
The part I seem to be stuck at is when the program displays all numbers in range 0-N that are "super numbers". I have concluded I need a loop in order to solve this, but I do not know how to go about it. So, for example, the program is supposed to read all the numbers from 0-50 and whenever the number is super it displays it. So it only displays 1 and 2 since they are considered super
enter integer: 50
2 is super
1 is super
I have written two functions; the first is a regular factorial program, and the second is a program that sums the factorials of the digits:
number = int(input ("enter integer: "))
def factorial (n):
result = 1
i = n * (n-1)
while n >= 1:
result = result * n
n = n-1
return result
#print(factorial(number))
def breakdown (n):
breakdown_num = 0
remainder = 0
if n < 10:
breakdown_num += factorial(n)
return breakdown_num
else:
while n > 10:
digit = n % 10
remainder = n // 10
breakdown_num += factorial(digit)
#print (str(digit))
#print(str(breakdown_num))
n = remainder
if n < 10 :
#print (str(remainder))
breakdown_num += factorial(remainder)
#print (str(breakdown_num))
return breakdown_num
#print(breakdown(number))
if (breakdown(number)) == number:
print(str(number)+ " is super")
Existing answers already show how to do the final loop to tie your functions together. Alternatively, you can also make use of more builtin functions and libraries, like sum, or math.factorial, and for getting the digits, you can just iterate the characters in the number's string representation.
This way, the problem can be solved in a single line of code (though it might be better to move the is-super check to a separate function).
def issuper(n):
return sum(math.factorial(int(d)) for d in str(n)) == n
N = 1000
res = [n for n in range(1, N+1) if issuper(n)]
# [1, 2, 145]
First I would slightly change how main code is executed, by moving main parts to if __name__ == '__main__', which will execute after running this .py as main file:
if __name__ == '__main__':
number = int(input ("enter integer: "))
if (breakdown(number)) == number:
print(str(number)+ " is super")
After that it seems much clearer what you should do to loop over numbers, so instead of above it would be:
if __name__ == '__main__':
number = int(input ("enter integer: "))
for i in range(number+1):
if (breakdown(i)) == i:
print(str(i)+ " is super")
Example input and output:
enter integer: 500
1 is super
2 is super
145 is super
Small advice - you don't need to call str() in print() - int will be shown the same way anyway.
I haven't done much Python in a long time but I tried my own attempt at solving this problem which I think is more readable. For what it's worth, I'm assuming when you say "displays all numbers in range 0-N" it's an exclusive upper-bound, but it's easy to make it an inclusive upper-bound if I'm wrong.
import math
def digits(n):
return (int(d) for d in str(n))
def is_super(n):
return sum(math.factorial(d) for d in digits(n)) == n
def supers_in_range(n):
return (x for x in range(n) if is_super(x))
print(list(supers_in_range(150))) # [1, 2, 145]
I would create a lookup function that tells you the factorial of a single digit number. Reason being - for 888888 you would recompute the factorial of 8 6 times - looking them up in a dict is much faster.
Add a second function that checks if a number isSuper() and then print all that are super:
# Lookup table for single digit "strings" as well as digit - no need to use a recursing
# computation for every single digit all the time - just precompute them:
faks = {0:1}
for i in range(10):
faks.setdefault(i,faks.get(i-1,1)*i) # add the "integer" digit as key
faks.setdefault(str(i), faks [i]) # add the "string" key as well
def fakN(n):
"""Returns the faktorial of a single digit number"""
if n in faks:
return faks[n]
raise ValueError("Not a single digit number")
def isSuper(number):
"Checks if the sum of each digits faktorial is the same as the whole number"
return sum(fakN(n) for n in str(number)) == number
for k in range(1000):
if isSuper(k):
print(k)
Output:
1
2
145
Use range.
for i in range(number): # This iterates over [0, N)
if (breakdown(number)) == number:
print(str(number)+ " is super")
If you want to include number N as well, write as range(number + 1).
Not quite sure about what you are asking for. From the two functions you write, it seems you have solid knowledge about Python programming. But from your question, you don't even know how to write a simple loop.
By only answering your question, what you need in your main function is:
for i in range(0,number+1):
if (breakdown(i)) == i:
print(str(i)+ " is super")
import math
def get(n):
for i in range(n):
l1 = list(str(i))
v = 0
for j in l1:
v += math.factorial(int(j))
if v == i:
print(i)
This will print all the super numbers under n.
>>> get(400000)
1
2
145
40585
I dont know how efficient the code is but it does produce the desired result :
def facto():
minr=int(input('enter the minimum range :')) #asking minimum range
maxr=int(input('enter the range maximum range :')) #asking maximum range
i=minr
while i <= maxr :
l2=[]
k=str(i)
k=list(k) #if i=[1,4,5]
for n in k: #taking each element
fact=1
while int(n) > 0: #finding factorial of each element
n=int(n)
fact=fact*n
n=n-1
l2.append(fact) #keeping factorial of each element eg : [1,24,120]
total=sum(l2) # taking the sum of l2 list eg 1+24+120 = 145
if total==i: #checking if sum is equal to the present value of i.145=145
print(total) # if sum = present value of i than print the number
i=int(i)
i=i+1
facto()
input : minr =0 , maxr=99999
output :
1
2
145
40585

Categories