Генерация паролей на python с условиями
Сгенерировать пароль, используя только random.choice с условиями:
- Заглавных букв в пароле должно быть от 20% до 30% от числа символов.
- Заглавные буквы не должны идти подряд.
Подскажите, как это реализовать без сторонних библиотек.
import random
count_symvol = int(input('Введите число не менее 6: '))
spisok = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g', 'H', 'h', 'I', 'i', 'J', 'j', 'K', 'k', 'L', 'l', 'M', 'm', 'N', 'n', 'O', 'o', 'P', 'p', 'Q', 'q', 'R', 'r', 'S', 's', 'T', 't', 'U', 'u', 'V', 'v', 'W', 'w', 'X', 'x', 'Y', 'y', 'Z', 'z')
arr_pass = []
for i in range(0, count_symvol):
arr_pass.append(random.choice(spisok))
print(arr_pass)
Ответы (3 шт):
У меня так получилось. Правда, не смог избавиться от функции sample. Еë можно заменить на перемешивание массива.
from random import choice, sample
n = 20
numBig = choice(range(int(n * 0.2), int(n * 0.3) + 1))
ascii_uppercase ='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
other = '0123456789abcdefghijklmnopqrstuvwxyz'
res = ""
def random_combination(iterable, r):
"Random selection from itertools.combinations(iterable, r)"
pool = tuple(iterable)
n = len(pool)
indices = sorted(sample(range(n), r))
return tuple(pool[i] for i in indices)
bigPositions = random_combination(range(n - numBig + 1), numBig)
bigCounter = 0
otherCounter = 0
for i in range(n - numBig + 1):
if bigCounter < numBig and bigPositions[bigCounter] == i:
res += choice(ascii_uppercase)
bigCounter += 1
if len(res) < n:
res += choice(other)
print(res)
Могу предложить такой вариант. Берем делаем две случайные строки через random.SystemRandom().choice(): первая — только заглавные, вторая — строчные и цифры. Затем смешиваем через zip() и выводим. Если random.SystemRandom().shuffle() не разрешается, то можно строку r.shuffle закомментить
from random import SystemRandom
from string import ascii_uppercase, ascii_lowercase, digits
def gen_password(count: int, upper_perc: int = 30):
r = SystemRandom()
upper_count = count * upper_perc // 100
upper = [r.choice(list(ascii_uppercase)) for _ in range(upper_count)] + [None] * (count - upper_count)
r.shuffle(upper)
other = [r.choice(list(ascii_lowercase + digits)) for _ in range(count - upper_count)]
symb = zip(upper, other) if r.randint(0, 1) else zip(other, upper)
return ''.join([c for r in symb for c in r if c])
print(gen_password(18))
Если прям совсем нужно учитывать условие и использовать только random.choice, то могу предложить такой код. Здесь заглавные буквы не идут подряд, а чередуются, что не нарушает условие из 2-го пункта.
from random import choice
ascii_uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
other_strings = 'abcdefghijklmnopqrstuvwxyz0123456789'
if __name__ == '__main__':
str_count = int(input())
if str_count >= 6:
password = ""
password += choice(other_strings + ascii_uppercase)
# индекс для цикла, чтобы не уйти в лимит символов верхнего регистра
if password.isupper():
upper_index = 1
else:
upper_index = 0
# максимальное число букв в верхнем регистре в районе 20-30%
str_upper_count = choice(range(int(str_count * 0.2), int(str_count * 0.3) + 1))
for i in range(str_count-1):
if password[i].islower() and upper_index < str_upper_count:
password += choice(ascii_uppercase)
upper_index += 1
else:
password += choice(other_strings)
print(password)
Вывод программы:
6
Urwdss
32
FqL9hYiS1lX36yO73eSkGih8wlhd1ma2