Bash on * 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
Agar berfungsi dengan benar, $a
tidak harus diatur ke kata sandi yang valid tetapi tidak acak di muka. Jika Anda ingin memasukkan a=
dan garis memecah di depan, itu tiga karakter lagi tetapi memungkinkan Anda untuk menjalankannya berulang kali. Anda jelas dapat juga mengganti semua baris baru dengan ;
sehingga Anda memiliki satu-baris yang dapat Anda jalankan sesering mungkin.
Selain itu, Anda harus menetapkan LC_ALL=C
atau tidak menyetel variabel lingkungan spesifik-lokal apa pun ( LANG
dan LC_CTYPE
khususnya), karena rentang karakter bergantung pada urutan kolasi yang sama dengan urutan ascii.
/dev/urandom
adalah sumber byte acak. !-~
adalah rentang semua karakter yang diizinkan, sebagaimana ditentukan dalam pertanyaan. tr -dc
menghapus semua karakter yang tidak tercantum dalam argumen berikutnya. head
mengambil 15 dari karakter yang tersisa. grep
memeriksa apakah masing-masing jenis yang diperlukan memang terjadi setidaknya satu kali. Inputnya terdiri dari empat salinan kandidat, sehingga urutan simbol tidak menjadi masalah, karenanya semua kata sandi yang memungkinkan berpeluang terpilih. Untuk -q
grep menekan output.
Untuk alasan yang tidak diketahui, /dev/random
alih-alih /dev/urandom
membutuhkan waktu lama. Sepertinya entropi cepat habis. Jika Anda cd
ke dalam /dev
, Anda dapat menghindari beberapa byte lagi, tapi yang terasa agak seperti kecurangan.
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
Untuk membuat kode dapat dibaca, saya menambahkan baris baru dan lekukan setelah loop yang tidak perlu dan yang saya tidak hitung.
Ini pada dasarnya ide yang sama seperti di versi bash. Sumber acak di sini adalah random.sample
, yang tidak akan mengulangi elemen. Untuk mengatasi fakta ini, kami menggunakan 15 salinan dari daftar surat yang diizinkan. Dengan begitu, setiap kombinasi masih dapat terjadi, meskipun yang dengan huruf berulang akan lebih jarang terjadi. Tapi saya memutuskan untuk mempertimbangkan ini sebagai fitur, bukan bug, karena pertanyaannya tidak memerlukan probabilitas yang sama untuk semua permutasi, hanya kemungkinan.
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)
Satu baris baru dan satu indentasi lagi tidak dihitung. Terlepas dari beberapa sintaksis Python-3 khusus ini adalah solusi yang sama seperti untuk 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)
Saya menambahkan baris baru untuk keterbacaan, tetapi tidak menghitungnya.
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
Linebreak dan lekukan di dalam loop ditambahkan tetapi tidak dihitung. Jika Anda menginginkannya, Anda dapat memindahkan ini lagi ke satu ;
baris terpisah.