The goal is to get from string $a="NewYork" new string without lowercase that stands before uppercase.
In this example, we should get output "NeYork"
I tried to do this through positions of small and big letters in ASCII table, but it doesn't work. I'm not sure is it possible to to do this in similar way, through positions in ASCII table.
function delete_char($a)
{
global $b;
$a = 'NewYork';
for($i =0; $i<strlen($a); $i++)
{
if( ord($a[$i])< ord($a[$i+1])){//this solves only part of a problem
chop($a,'$a[$i]');
}
else{
$b.=$a[$i];
}
}
return $b;
}
This is something a regular expression handles with ease
<?php
$a ="NewYorkNewYork";
$reg="/[a-z]([A-Z])/";
echo preg_replace($reg, "$1", $a); // NeYorNeYork
The regular expression searches for a lower case letter followed by an upper case letter, and captures the upper case one. preg_replace() then replace that combination with just the captured letter ($1).
See https://3v4l.org/o43bO
You don't need to capture the uppercase letter and use a backreference in the replacement string.
More simply, match the lowercase letter then use a lookahead for an uppercase letter -- this way you only replace the lowercase character with an empty string. (Demo)
echo preg_replace('~[a-z](?=[A-Z])~', '', 'NewYork');
// NeYork
As for a review of your code, there are multiple issues.
global $b doesn't make sense to me. You need the variable to be instantiated as an empty string within the scope of the custom function only. It more simply should be $b = '';.
The variable and function naming is unhelpful. A function's name should specifically describe the function's action. A variable should intuitively describe the data that it contains. Generally speaking, don't sacrifice clarity for brevity.
As a matter of best practice, you should not repeatedly call a function when you know that the value has not changed. Calling strlen() on each iteration of the loop is not beneficial. Declare $length = strlen($input) and use $length over and over.
$a[$i+1] is going to generate an undefined offset warning on the last iteration of the loop because there cannot possibly be a character at that offset when you already know the length of the string has been fully processed. In other words, the last character of a string will have an offset of "length - 1". There is more than one way to address this, but I'll use the null coalescing operator to set a fallback character that will not qualify the previous letter for removal.
Most importantly, you cannot just check that the current ord value is less than the next ord value. See here that lowercase letters have an ordinal range of 97 through 122 and uppercase letters have an ordinal range of 65 through 90. You will need to check that both letters meet the qualifying criteria for the current letter to be included in the result string.
Rewrite: (Demo)
function removeLowerCharBeforeUpperChar(string $input): string
{
$output = '';
$length = strlen($input);
for ($offset = 0; $offset < $length; ++$offset) {
$currentOrd = ord($input[$offset]);
$nextOrd = ord($input[$offset + 1] ?? '_');
if ($currentOrd < 97
|| $currentOrd > 122
|| $nextOrd < 65
|| $nextOrd > 90
){
$output .= $input[$offset];
}
}
return $output;
}
echo removeLowerCharBeforeUpperChar('MickMacKusa');
// MicMaKusa
Or with ctype_ functions: (Demo)
function removeLowerCharBeforeUpperChar(string $input): string
{
$output = '';
$length = strlen($input);
for ($offset = 0; $offset < $length; ++$offset) {
$nextLetter = $input[$offset + 1] ?? '';
if (ctype_lower($input[$offset]) && ctype_upper($nextLetter)) {
$output .= $nextLetter; // omit current letter, save next
++$offset; // double iterate
} else {
$output .= $input[$offset]; // save current letter
}
}
return $output;
}
To clarify, I would not use the above custom function in a professional script and both snippets are not built to process strings containing multibyte characters.
Simply, I create new variable $s used for store new string to be returned and a make loop iterate over $a string, I used ctype_upper to check if next character not uppercase append it to $s. at the end i return $s concatenate with last char of string.
function delete_char(string $a): string
{
if(!strlen($a))
{
return '';
}
$s='';
for($i = 0; $i < strlen($a)-1; $i++)
{
if(!ctype_upper($a[$i+1])){
$s.=$a[$i];
}
}
return $s.$a[-1];
}
echo delete_char("NewYork");//NeYork
Something like this maybe?
<?php
$word = 'NewYork';
preg_match('/.[A-Z].*/', $word, $match);
if($match){
$rlen = strlen($match[0]); //length from character before capital letter
$start = strlen($word)-$rlen; //first lower case before the capital
$edited_word = substr_replace($word, '', $start, 1); //removes character
echo $edited_word; //prints NeYork
}
?>
So while i was doing my homework i stuck on one point.
The excercise is based on making a function which checks if $word is a palindrome, from my tests $L works and is moving forward to right side of the word ($L starts from left, $R from right)
but $R is not working at all, if $R is swapped by a number - it works. If $R is printed, it shows right number - 5.
$word = "madam";
function palindrome($s)
{
$i = intval(strlen($s) / 2);
$L = 0;
$R = strlen($s);
$pal = true;
for($i; $i>0; $i--)
{
if($s[$L] != $s[$R]) $pal=false;
$L++;
$R--;
}
if($pal==true)
print("palindrome");
else
print("not a palindrome");
}
palindrome($word);
I expect to make $R an value, i suspect that PHP sees it as a string, not an integer, but i don't know why. I would be very happy if someone helped me with that.
If you consider string as char table, index starts at 0, but strlen count from 1 so if you have 'madam' then strlen() returns 5 but last chatacter is on $s[4], simply use:
$R = strlen($s)-1;
As a quick, off the top of my head sort of idea... no loops, just some simple string splitting, this works to check if the given string ($s) is a palindrome.
function palindrome($s) {
// split the string in two
$left = substr($s, 0, floor(strlen($s)/2));
$right = substr($s, 0-strlen($left));
// if the left half matches the REVERSE of the right
// you've got a palindrome
return $left === strrev($right);
}
$word = "madam";
echo palindrome($word) ? "Yup" : "Nope";
Basically, it just chops the word in half - reverses the right half and compares it to the left. If they match, it's a palindrome - currently it's case-sensitive though so "Madam" won't be a palindrome but that can be easily tweaked by lower-casing the whole thing first.
I am trying to generate random voucher code applying the following rules:
Alphanumeric combination 5 characters in capital case (A-Z, 0-9, and take away 1, 0, I, O).
This is my try
<?php
function generateRandomString($length = 5) {
return substr(str_shuffle("23456789ABCDEFGHIJKMNPQRSTUVWXYZ"), 0, $length);
}
echo generateRandomString();
?>
but i am not sure if there is a better way of doing this
If you need to call this function lots of times, your current implementation will be very slow, because it uses much more calls of random function than it is necessary (if $length < 32). Also if your set of allowed characters is smaller than number of characters in the result, your current implementation will return wrong result too. And also your implementation does not allow repeating of characters in the result, but in the specification it is not forbidden to repeat characters.
A little more accurate solution is to use array_rand():
function generateRandomString($length = 5) {
$allowed = str_split('23456789ABCDEFGHIJKMNPQRSTUVWXYZ'); // it is enough to do it once
$res = '';
foreach (array_rand($allowed, $length) as $k)
$res .= $allowed[$k];
return $res;
}
function generateRandom($length = 5) {
$possibleChars = '123456789ABCDEFGHJKMNPQRSTUVWXYZ';
$rndString = '';
for ($i = 0; $i < $length; $i++) {
$rndString .= $possibleChars[rand(0, strlen($possibleChars) - 1)];
}
return $rndString;
}
echo generateRandom();
Here you can define the characters which you want to have in your random string.
The problem with your function is that any char will be just used 1 time per call. Its not really random. And the lenght of the random string would also be limited to the amount of characters you have.
For example: AAAAA is not possible with your function, with mine it is.
If you need a string longer than your charset, that method will fail. Please can you try the code below;
<?php
function generateRandomString($length = 5) {
$chars = "23456789ABCDEFGHIJKMNPQRSTUVWXYZ"; //Your char-set
$charArray = str_split($chars); //Your array representation of chars
$charCount = strlen($chars); //Your char-set length
$result = "";
//Loop throught required `$length`
for($i=1;$i<=$length;$i++)
{
$randChar = rand(0,$charCount-1); //Pick a random char in range of our chars
$result .= $charArray[$randChar]; //Concatenate picked char to result
}
return $result;
}
echo generateRandomString(75);
?>
Here is a working example: https://ideone.com/D1EQ9T
Hope this helps.
I am trying to calculate a few 'streaks', specifically the highest number of wins and losses in a row, but also most occurences of games without a win, games without a loss.
I have a string that looks like this; 'WWWDDWWWLLWLLLL'
For this I need to be able to return:
Longest consecutive run of W charector (i will then replicate for L)
Longest consecutive run without W charector (i will then replicate for L)
I have found and adapted the following which will go through my array and tell me the longest sequence, but I can't seem to adapt it to meet the criteria above.
All help and learning greatly appreciated :)
function getLongestSequence($sequence){
$sl = strlen($sequence);
$longest = 0;
for($i = 0; $i < $sl; )
{
$substr = substr($sequence, $i);
$len = strspn($substr, $substr{0});if($len > $longest)
$longest = $len;
$i += $len;
}
return $longest;
}
echo getLongestSequence($sequence);
You can use a regular expression to detect sequences of identical characters:
$string = 'WWWDDWWWLLWLLLL';
// The regex matches any character -> . in a capture group ()
// plus as much identical characters as possible following it -> \1+
$pattern = '/(.)\1+/';
preg_match_all($pattern, $string, $m);
// sort by their length
usort($m[0], function($a, $b) {
return (strlen($a) < strlen($b)) ? 1 : -1;
});
echo "Longest sequence: " . $m[0][0] . PHP_EOL;
You can achieve the maximum count of consecutive character in a particular string using the below code.
$string = "WWWDDWWWLLWLLLL";
function getLongestSequence($str,$c) {
$len = strlen($str);
$maximum=0;
$count=0;
for($i=0;$i<$len;$i++){
if(substr($str,$i,1)==$c){
$count++;
if($count>$maximum) $maximum=$count;
}else $count=0;
}
return $maximum;
}
$match="W";//change to L for lost count D for draw count
echo getLongestSequence($string,$match);
I know that the rand function in PHP generates random integers, but what is the best way to generate a random string such as:
Original string, 9 chars
$string = 'abcdefghi';
Example random string limiting to 6 chars
$string = 'ibfeca';
UPDATE: I have found tons of these types of functions, basically I'm trying to understand the logic behind each step.
UPDATE: The function should generate any amount of chars as required.
Please comment the parts if you reply.
If you want to allow repetitive occurences of characters, you can use this function:
function randString($length, $charset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
{
$str = '';
$count = strlen($charset);
while ($length--) {
$str .= $charset[mt_rand(0, $count-1)];
}
return $str;
}
The basic algorithm is to generate <length> times a random number between 0 and <number of characters> − 1 we use as index to pick a character from our set and concatenate those characters. The 0 and <number of characters> − 1 bounds represent the bounds of the $charset string as the first character is addressed with $charset[0] and the last with $charset[count($charset) - 1].
Well, you didn't clarify all the questions I asked in my comment, but I'll assume that you want a function that can take a string of "possible" characters and a length of string to return. Commented thoroughly as requested, using more variables than I would normally, for clarity:
function get_random_string($valid_chars, $length)
{
// start with an empty random string
$random_string = "";
// count the number of chars in the valid chars string so we know how many choices we have
$num_valid_chars = strlen($valid_chars);
// repeat the steps until we've created a string of the right length
for ($i = 0; $i < $length; $i++)
{
// pick a random number from 1 up to the number of valid chars
$random_pick = mt_rand(1, $num_valid_chars);
// take the random character out of the string of valid chars
// subtract 1 from $random_pick because strings are indexed starting at 0, and we started picking at 1
$random_char = $valid_chars[$random_pick-1];
// add the randomly-chosen char onto the end of our string so far
$random_string .= $random_char;
}
// return our finished random string
return $random_string;
}
To call this function with your example data, you'd call it something like:
$original_string = 'abcdefghi';
$random_string = get_random_string($original_string, 6);
Note that this function doesn't check for uniqueness in the valid chars passed to it. For example, if you called it with a valid chars string of 'AAAB', it would be three times more likely to choose an A for each letter as a B. That could be considered a bug or a feature, depending on your needs.
My favorite:
echo substr(md5(rand()), 0, 7);
So, let me start off by saying USE A LIBRARY. Many exist:
RandomCompat
RandomLib
SecurityMultiTool
The core of the problem is almost every answer in this page is susceptible to attack. mt_rand(), rand(), lcg_value() and uniqid() are all vulnerable to attack.
A good system will use /dev/urandom from the filesystem, or mcrypt_create_iv() (with MCRYPT_DEV_URANDOM) or openssl_pseudo_random_bytes(). Which all of the above do. PHP 7 will come with two new functions random_bytes($len) and random_int($min, $max) that are also safe.
Be aware that most of those functions (except random_int()) return "raw strings" meaning they can contain any ASCII character from 0 - 255. If you want a printable string, I'd suggest running the result through base64_encode().
function generate_random_string($name_length = 8) {
$alpha_numeric = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
return substr(str_shuffle(str_repeat($alpha_numeric, $name_length)), 0, $name_length);
}
Updated the code as per mzhang's great suggestion in the comments below.
A better and updated version of #taskamiski's excellent answer:
Better version, using mt_rand() instead of rand():
echo md5(mt_rand()); // 32 char string = 128bit
Even better, for longer strings, using the hash() function that allows to select hashing algorithmns:
echo hash('sha256', mt_rand()); // 64 char string
echo hash('sha512', mt_rand()); // 128 char string
If you want to cut the result down to let's say 50 chars, do it like this:
echo substr(hash('sha256', mt_rand()), 0, 50); // 50 char string
Joining characters at the end should be more efficient that repeated string concatenation.
Edit #1: Added option to avoid character repetition.
Edit #2: Throws exception to avoid getting into infinite loop if $norepeat is selected and $len is greater than the charset to pick from.
Edit #3: Uses array keys to store picked random characters when $norepeat is selected, as associative array key lookup is faster than linearly searching the array.
function rand_str($len, $norepeat = true)
{
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$max = strlen($chars) - 1;
if ($norepeat && len > $max + 1) {
throw new Exception("Non repetitive random string can't be longer than charset");
}
$rand_chars = array();
while ($len) {
$picked = $chars[mt_rand(0, $max)];
if ($norepeat) {
if (!array_key_exists($picked, $rand_chars)) {
$rand_chars[$picked] = true;
$len--;
}
}
else {
$rand_chars[] = $picked;
$len--;
}
}
return implode('', $norepeat ? array_keys($rand_chars) : $rand_chars);
}
this will generate random string
function generateRandomString($length=10) {
$original_string = array_merge(range(0,9), range('a','z'), range('A', 'Z'));
$original_string = implode("", $original_string);
return substr(str_shuffle($original_string), 0, $length);
}
echo generateRandomString(6);
I think I will add my contribution here as well.
function random_string($length) {
$bytes_1 = openssl_random_pseudo_bytes($length);
$hex_1 = bin2hex($bytes_1);
$random_numbers = substr(sha1(rand()), 0, $length);
$bytes_2 = openssl_random_pseudo_bytes($length);
$hex_2 = bin2hex($bytes_2);
$combined_chars = $hex_1 . $random_numbers . $hex_2;
$chars_crypted = hash('sha512', $combined_chars);
return $chars_crypted;
}
Thanks
Most aspects of this have already been discussed, but i'd recommend a slight update:
If you are using this for retail usage, I would avoid the domain
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
and instead use:
ABCDEFGHJKMNPQRSTUVWXY3456789
Granted, you end up with far fewer characters, but it saves a great deal of hassle, as customers cannot mistake 0 for O, or 1 for l or 2 for Z. Also, you can do an UPPER on the input and customers can then enter upper or lower case letters -- that is also sometimes confusing since they can look similar.
What do you need a random string for?
Is this going to be used for anything remotely analogous to a password?
If your random string requires any security properties at all, you should use PHP 7's random_int() function instead of all the insecure mt_rand() answers in this thread.
/**
* Generate a random string
*
* #link https://paragonie.com/b/JvICXzh_jhLyt4y3
*
* #param int $length - How long should our random string be?
* #param string $charset - A string of all possible characters to choose from
* #return string
*/
function random_str($length = 32, $charset = 'abcdefghijklmnopqrstuvwxyz')
{
// Type checks:
if (!is_numeric($length)) {
throw new InvalidArgumentException(
'random_str - Argument 1 - expected an integer'
);
}
if (!is_string($charset)) {
throw new InvalidArgumentException(
'random_str - Argument 2 - expected a string'
);
}
if ($length < 1) {
// Just return an empty string. Any value < 1 is meaningless.
return '';
}
// This is the maximum index for all of the characters in the string $charset
$charset_max = strlen($charset) - 1;
if ($charset_max < 1) {
// Avoid letting users do: random_str($int, 'a'); -> 'aaaaa...'
throw new LogicException(
'random_str - Argument 2 - expected a string at least 2 characters long'
);
}
// Now that we have good data, this is the meat of our function:
$random_str = '';
for ($i = 0; $i < $length; ++$i) {
$r = random_int(0, $charset_max);
$random_str .= $charset[$r];
}
return $random_str;
}
If you aren't on PHP 7 yet (which is probably the case, as it hasn't been released as of this writing), then you'll want paragonie/random_compat, which is a userland implementation of random_bytes() and random_int() for PHP 5 projects.
For security contexts, always use random_int(), not rand(), mt_rand(), etc. See ircmaxell's answer as well.
built on top of https://stackoverflow.com/a/853898/533426
but with php 7 cryptographically secure random function and lower AND upper case alphabet
function random($length = 8){
$valid_chars ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
// start with an empty random string
$random_string = "";
// count the number of chars in the valid chars string so we know how many choices we have
$num_valid_chars = strlen($valid_chars);
// repeat the steps until we've created a string of the right length
for ($i = 0; $i < $length; $i++)
{
// pick a random number from 1 up to the number of valid chars
$random_pick = random_int(1, $num_valid_chars);
// take the random character out of the string of valid chars
// subtract 1 from $random_pick because strings are indexed starting at 0, and we started picking at 1
$random_char = $valid_chars[$random_pick-1];
// add the randomly-chosen char onto the end of our string so far
$random_string .= $random_char;
}
// return our finished random string
return $random_string;
}
//example output XjdXHakZ, yBG8hpZG, L6jg4FpK
// #author http://codeascraft.etsy.com/2012/07/19/better-random-numbers-in-php-using-devurandom/
function devurandom_rand($min = 0, $max = 0x7FFFFFFF)
{
$diff = $max - $min;
if ($diff < 0 || $diff > 0x7FFFFFFF) {
throw new RuntimeException('Bad range');
}
$bytes = mcrypt_create_iv(4, MCRYPT_DEV_URANDOM);
if ($bytes === false || strlen($bytes) != 4) {
throw new RuntimeException('Unable to get 4 bytes');
}
$ary = unpack('Nint', $bytes);
$val = $ary['int'] & 0x7FFFFFFF; // 32-bit safe
$fp = (float) $val / 2147483647.0; // convert to [0,1]
return round($fp * $diff) + $min;
}
function build_token($length = 60, $characters_map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') {
$map_length = mb_strlen($characters_map)-1;
$token = '';
while ($length--) {
$token .= mb_substr($characters_map, devurandom_rand(0,$map_length),1);
}
return $token;
}
This will work only in UNIX environment where PHP is compiled with mcrypt.
Do you want to create your password by a random permutation of the original letters? Should it just contain unique characters?
Use rand to choose random letters by index.
This is an old question but I want try to post my solution... I always use this my function to generate a custom random alphanumeric string...
<?php
function random_alphanumeric($length) {
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345689';
$my_string = '';
for ($i = 0; $i < $length; $i++) {
$pos = mt_rand(0, strlen($chars) -1);
$my_string .= substr($chars, $pos, 1);
}
return $my_string;
}
$test = random_alphanumeric(50); // 50 characters
echo $test;
?>
test: UFOruSSTCPIqxTRIIMTRkqjOGidcVlhYaS9gtwttxglheVugFM
if you need two or more unique strings you can use this trick...
$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
while ($string_1 == $string_2) {
$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
if ($string_1 != $string_2) {
break;
}
}
echo $string_1;
echo "<br>\n";
echo $string_2;
$string_1: tMYicqLCHEvENwYbMUUVGTfkROxKIekEB2YXx5FHyVByp3mlJO
$string_2: XdMNJYpMlFRKFDlF6GhVn6jsBVNQ1BCCevj8yK2niFOgpDI2MU
I hope this help.
echo substr(bin2hex(random_bytes(14)), 0, $length);
this code gets a random bytes, that are converted from binary to hexadecimal, and then takes a substring of this hexadecimal string, as long you puts in $length variable
Try this
Simple enough!
function RandomFromCharset($charset,$length)
{
$characters = $charset; // your existing charset / defined string
$charactersLength = strlen($characters);
$random_from_charset = '';
for ($i = 0; $i < $length; $i++)
{
$random_from_charset.= $characters[rand(0, $charactersLength - 1)];
}
return random_from_charset;
}
Call the function as follows
RandomFromCharset($charset,$length);
where $length will be length of random string you want (this can be predefined also in the function as RandomFromCharset(charset,$length=10) ) to generate and $charset will be your existing string to which you want to restrict the characters.
One approach is to generate an md5 from a random number and extract the number of characters you want:
<?php
$random = substr(md5(mt_rand()), 0, 7);
echo $random;
?>
mt_rand will generate a random number, md5 will create a 32 character string (containing both letters and numbers) and, in this example, we're extracting the first 7 characters of text.
you could make an array of characters then use rand() to pick a letter from the array and added it to a string.
$letters = array( [0] => 'a' [1] => 'b' [2] => 'c' [3] => 'd' ... [25] = 'z');
$lengthOfString = 10;
$str = '';
while( $lengthOfString-- )
{
$str .= $letters[rand(0,25)];
}
echo $str;
*note that this does allow repeat characters
This builds on Gumbo's solution by adding functionality to list a set of characters to be skipped in the base character set. The random string selects characters from $base_charset which do not also appear in $skip_charset.
/* Make a random string of length using characters from $charset, excluding $skip_chars.
* #param length (integer) length of return value
* #param skip_chars (string) characters to be excluded from $charset
* #param charset (string) characters of posibilities for characters in return val
* #return (string) random string of length $length */
function rand_string(
$length,
$skip_charset = '',
$base_charset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'){
$skip_len = strlen($skip_charset);
for ($i = 0; $i<$skip_len; $i++){
$base_charset = str_replace($skip_charset[$i], '', $base_charset);
}
cvar_dump($base_charset, '$base_charset after replace');
$str = '';
$count = strlen($base_charset);
while ($length--) {
$str .= $base_charset[mt_rand(0, $count - 1)];
}
return $str;
}
Here are some usage examples. The first two examples use the default value for $base_charset. The last example explicitly defines $base_charset.
echo rand_string(15, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
// 470620078953298
echo rand_string(8, 'abcdefghijklmnopqrstuvwxyz0123456789');
// UKLIHOTFSUZMFPU
echo rand_string(15, 'def', 'abcdef');
// cbcbbccbabccaba
well, I was looking for a solution, and I kindda used #Chad Birch's solution merged with #Gumbo's one. This is what I came up with:
function get_random_string($length, $valid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456790!·$%&/()=?¿¡',.-;:+*`+´ç")
{
$random_string = "";
$num_valid_chars = strlen($valid_chars);
for ($i = 0; $i < $length; $i++, $random_string .= $valid_chars[mt_rand(1, $num_valid_chars)-1]);
return $random_string;
}
I think comments are pretty much unnecesary since the answers I used to build up this one are already thoroughly commented. Cheers!
If you're not concerned about time, memory, or cpu efficiency, and if your system can handle it, why not give this algorithm a try?!
function randStr($len, $charset = 'abcdABCD0123') {
$out = '';
$str = array();
for ($i = 0; $i < PHP_INT_MAX; $i++) {
$str[$i] = $charset;
shuffle($str);
$charset .= implode($charset, $str);
$charset = str_shuffle($charset);
}
$str = array_flip($str);
$str = array_keys($str);
for ($i = 0; $i < PHP_INT_MAX; $i++) {
shuffle($str);
}
$str = implode('', $str);
for ($i = 0; $i < strlen($str); $i++) {
$index = mt_rand(1, strlen($str));
$out .= $str[$index - 1];
}
for ($i = 0; $i < PHP_INT_MAX; $i++) {
$out = str_shuffle($out);
}
return substr($out, 0, $len);
}
Maybe this will read better if it uses recursion, but I'm not sure if PHP uses tail recursion or not...