Баш на * 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
grep" пригнічує вихід.
З невідомих причин /dev/random
замість /dev/urandom
віків. Схоже, що ентропія досить швидко вичерпалася. Якщо ви cd
ввійдете /dev
, ви можете уникнути ще кількох байтів, але це трохи схоже на обман.
Пітон 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
Розрив рядка та відступ всередині циклу додано, але не враховується. Якщо вам це подобається, ви можете знову перемістити це в єдиний ;
розділений рядок.