Bash na * 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
Aby działać poprawnie, $a
nie może być ustawione na prawidłowe, ale nieprzypadkowe hasło z góry. Jeśli chcesz dołączyć a=
i linię z przodu, to trzy kolejne znaki, ale pozwala ci to powtarzać. Oczywiście możesz również zastąpić wszystkie nowe wiersze, ;
aby mieć linijkę, którą możesz wykonywać tak często, jak chcesz.
Ponadto powinno być ustawione LC_ALL=C
czy nie ustawić jakieś zmienne środowiskowe locale specyficzne ( LANG
a LC_CTYPE
zwłaszcza), ponieważ zakresy znaków zależą kolejność sortowania jest równa kolejności ASCII.
/dev/urandom
jest źródłem losowych bajtów. !-~
to zakres wszystkich dopuszczalnych znaków, jak określono w pytaniu. tr -dc
usuwa wszystkie znaki niewymienione w następnym argumencie. head
bierze 15 pozostałych postaci. grep
sprawdza, czy każdy z wymaganych rodzajów występuje przynajmniej raz. Jego dane wejściowe składają się z czterech kopii kandydata, więc kolejność symboli nie ma znaczenia, dlatego wszystkie możliwe hasła mają szansę zostać wybranymi. Opcja -q
grep tłumi wyjście.
Z nieznanych przyczyn /dev/random
zamiast na /dev/urandom
wieki. Wygląda na to, że entropia dość szybko się wyczerpała. Jeśli cd
w /dev
, można uniknąć jeszcze kilka bajtów, ale czuje się trochę jak oszustwo.
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
Aby kod był czytelny, dodałem nowy wiersz i wcięcie po pętli, które nie są konieczne i których nie policzyłem.
Jest to zasadniczo ten sam pomysł, co w wersji bash. Tutaj jest losowe źródło random.sample
, które nie będzie powtarzać elementów. Aby temu zaradzić, używamy 15 kopii listy dozwolonych liter. W ten sposób każda kombinacja może nadal występować, chociaż te z powtarzającymi się literami będą występować rzadziej. Ale decyduję się uznać to za cechę, a nie za błąd, ponieważ pytanie nie wymagało jednakowego prawdopodobieństwa dla wszystkich permutacji, tylko możliwość.
Python 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)
Jeden nowy wiersz i jedno tiret ponownie nie są liczone. Oprócz pewnych narzutów składni specyficznych dla Python-3 jest to to samo rozwiązanie, co dla 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)
Dodałem nowe wiersze dla czytelności, ale ich nie policzyłem.
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
Dodano przerwanie linii i wcięcie wewnątrz pętli, ale nie zostało zliczone. Jeśli masz na to ochotę, możesz ponownie przenieść to do pojedynczej ;
linii.