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; }