🗒 Задача¶
Создай программу, которая генерирует более сложные пароли.
-
пароль должен содержать цифры, строчные и заглавные буквы - должны присутствовать все три вида символов;
-
цифры и буквы должны располагаться в случайном порядке;
-
длина пароля должна задаваться пользователем;
-
минимальная длина пароля 6 символов.
❌ Ошибки¶
-
перечисляют весь алфавит в одну строку — предлагать делать через интервалы чаров
-
нет гарантированного наличия всех трех символов
-
при подходе из решения не перемешивают строку с паролем в конце
✏️ Комментарии¶
В данной реализации хоть ты и складываешь все три диапазона в один набор символов, но есть вероятность, что рандомайзер при генерации пароля упустит один или несколько типов символов.
Стоит изменить подход. Например, сперва добавлять обязательные символы, затем рандомно оставшиеся из общего набора.
Круто, но довольно размашесто получилось. Попробуем упростить?
Стоит изменить подход. Например, сперва добавлять обязательные символы, затем рандомно оставшиеся из общего набора.
Ок, но такой алгоритм с первыми тремя обязательными символами можно раскрыть и облегчить взломщику работу. Стоит еще конечную строку с паролем перемешать. Сделать это можно, используя extension `shuffle()`.
Тем самым обрати внимание на разницу методов `shuffle()` и `shuffled()` один перемешивает строку для которой вызван этот метод, другой возвращает новый перемешанный список. Разницу ты можешь увидеть, провалившись в декларацию этих методов.
Общий диапазон предлагаю создавать за пределами цикла, чтобы каждый раз его не инициализировать заново.
Вместо перечисления всех символов, можно использовать символьные диапазоны и складывать их вместе для получения одного общего набора символов. Например, вот так `val allChars = ('a'..'z') + ('A'..'Z') + ('0'..'9')`
Пустая строка в начале выглядит как костыль, чтобы сконкатенировать остальные символы справа.
На самом деле программу можно сделать проще, сократив ее в половину. Например:
1. Нам нужны обязательные символы. Поэтому далее в три строки добавляем через password.add() рандомный символ каждого типа.
2. Начиная с 4 символа и до максимальной длины пароля добиваем в цикле рандомными символами из allChars
3. В конце, чтобы пароль не скомпрометировали вызываем для переменной пароля shuffle(), чтобы его полностью перемешать.
Дальше уже всякие мелочи типа формирования строки и вывода.
Давай сделаем 3 отдельные переменные для каждого вида символов и еще переменную, скажем allChars, где эти символы сложем. Переменную password сделаем пустым списком, куда будут добавляться наши символы. Далее:
Нам нужны обязательные символы. Поэтому в три строки добавляем через password.add() рандомный символ каждого типа.
Начиная с 4 символа и до максимальной длины пароля добиваем в цикле рандомными символами из allChars
В конце, чтобы пароль не скомпрометировали вызываем для переменной пароля shuffle(), чтобы его полностью перемешать.
Тут уже детали реализации и вкусовщина, но выглядит сложновато (считать за "сложно читаемый код"). Как будто можно или предупреждение раньше выкидывать и вместо трайкач только условными ветвлениями обойтись.
В данной реализации есть вероятность, что рандомайзер при генерации пароля упустит один или несколько типов символов.
Стоит изменить подход. Например, сперва добавлять обязательные символы, затем рандомно оставшиеся из общего набора.
1. Сначала в три строки добавляем через password.add() рандомный символ каждого типа.
2. Начиная с 4 символа и до максимальной длины пароля добиваем в цикле рандомными символами, для этого предлагаю ввести отдельную переменную, где складываем все три диапазона в один набор символов.
3. В конце, чтобы пароль не скомпрометировали вызываем для переменной пароля shuffle(), чтобы его полностью перемешать.
🧾 Решение¶
fun main() {
print("Введите максимальную длину пароля. Не меньше $MAX_CHARS_COUNT символов: ")
val maxPasswordLength = readln().toIntOrNull() ?: MAX_CHARS_COUNT
val digits = '0'..'9'
val lowercaseLetters = 'a'..'z'
val uppercaseLetters = 'A'..'Z'
val allChars = digits + lowercaseLetters + uppercaseLetters
val password = mutableListOf<Char>()
password.add(digits.random())
password.add(lowercaseLetters.random())
password.add(uppercaseLetters.random())
for (i in 4..maxPasswordLength) {
password.add(allChars.random())
}
password.shuffle()
println(password.joinToString(""))
}
const val MAX_CHARS_COUNT = 6