That's a good idea. Here is a stab at it using String::Random. The sub generates a string of given length of 0,1,2 and then converts this to character codes that String::Random understands. The sub ensures that no three values in a row are the same.
use String::Random;
my $length = 10;
my $Random = new String::Random;
# add new pattern char for upper and lower case
$Random->{'A'} = [ 'A'..'Z', 'a'..'z' ];
my $pattern = generate_pattern($length);
my $password = $Random->randpattern($pattern);;
say $password;
sub generate_pattern
{
my $length = shift;
# populate first two values
my @chars = ( int(rand(3)), int(rand(3)) );
for my $i (2..$length-1)
{
# check if previous two values match
if ($chars[$i - 1] == $chars[$i - 2])
{
my @other_values = grep( !($_ == $chars[$i - 1]), (0..2));
# get random other value. ie if last two values were 1, pick
+0 or 2
$chars[$i] = $other_values[ int(rand(2)) ];
}
else
{
$chars[$i] = int(rand(3));
}
}
my $pattern = join '', @chars;
# convert random string of 0,1,2 to A,n,!
$pattern =~ tr/012/An!/;
return $pattern;
}
Edit: It's a little ugly, but this is quite a bit faster than the route I took in my other code sample above. |