Bash на * NIX (109)
while ! grep -Pq [A-Z].*[a-z].*[0-9].*[\\W_]<<<$a$a$a$a
do a=`tr -dc !-~</dev/urandom|head -c15`
done
echo $a
Для правильной работы $a
не должен быть установлен действительный, но неслучайный пароль заранее. Если вы хотите включить a=
и разрыв строки вперед, это еще три символа, но это позволяет вам запускать эту вещь несколько раз. Вы также можете заменить все новые строки на;
чтобы у вас была однострочная которую вы можете выполнять так часто, как пожелаете.
Кроме того, вы должны были установить LC_ALL=C
или не устанавливать какие-либо переменные среды, зависящие от локали ( LANG
иLC_CTYPE
зависящие от в частности), поскольку диапазоны символов зависят от порядка сопоставления, равного порядку ascii.
/dev/urandom
является источником случайных байтов. !-~
это диапазон всех допустимых символов, как указано в вопросе. tr -dc
удаляет все символы, не перечисленные в следующем аргументе. head
занимает 15 из оставшихся символов. grep
проверяет, встречается ли каждый из требуемых видов хотя бы один раз. Его ввод состоит из четырех копий кандидата, поэтому порядок символов не имеет значения, поэтому все возможные пароли имеют шанс быть выбранными. -q
К ГРЭП выход подавляет.
По неизвестным причинам, /dev/random
а не /dev/urandom
принимает возраст. Кажется, энтропия довольно быстро исчерпала себя. Если вы cd
в/dev
, вы можете избежать еще несколько байт, но чувствует себя немного как обман.
Python 2 (138)
import re,random
a=''
while not re.search('[A-Z].*[a-z].*[0-9].*[\W_]',a*4):
a=''.join(random.sample(map(chr,range(33,127))*15,15))
print a
Чтобы сделать код читабельным, я добавил новую строку и отступ после цикла, который не является необходимым и который я не учел.
По сути, это та же идея, что и в версии bash. Случайный источник здесь random.sample
, который не будет повторять элементы. Чтобы противостоять этому факту, мы используем 15 копий списка допустимых букв. Таким образом, любая комбинация все еще может иметь место, хотя повторяющиеся буквы встречаются реже. Но я решил считать это особенностью, а не ошибкой, поскольку вопрос не требовал равной вероятности для всех перестановок, только для возможности.
Питон 3 (145)
import re,random
a=''
while not re.search('[A-Z].*[a-z].*[0-9].*[\W_]',a*4):
a=''.join(random.sample(list(map(chr,range(33,127)))*15,15))
print(a)
Один перевод строки и один отступ снова не учитываются. Помимо некоторых накладных расходов на синтаксис, специфичных для Python-3, это то же решение, что и для Python 2.
JavaScript (161)
a=[];for(i=33;i<127;)a.push(s=String.fromCharCode(i++));
while(!/[A-Z].*[a-z].*[0-9].*[\W_]/.test(s+s+s+s))
for(i=0,s="";i<15;++i)s+=a[Math.random()*94|0];alert(s)
Я добавил новые строки для удобства чтения, но не посчитал их.
R (114)
s<-""
while(!grepl("[A-Z].*[a-z].*[0-9].*(\\W|_)",paste(rep(s,4),collapse="")))
s<-intToUtf8(sample(33:126,15,T))
s
Разрыв строки и отступ внутри цикла добавлены, но не учитываются. Если вам это нравится, вы можете снова переместить это в одну ;
строку.