skip to Main Content

I create a random string of a given length with the function below:

function generateRandomString($length) {
    $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[random_int(0, $charactersLength - 1)];
    }
    return $randomString;
}

This gives me a result of e.g. aBcDEFghIJKlmNo when giving it 15 as length.

Now I also have a variable number that can go from say 1 to 10.000.000. Let us say the number is 12.345 for simplicity, but the solution needs to work for any number in the range.

I need a function that takes this number 12.345 and puts the numbers consecutively into the string aBcDEFghIJKlmNo at random places, giving a result of e.g. ‘a1BcD23EFg4hIJ5KlmNo’.

function placeNumberInString($string, $number){
    $new_string = '';

    // I can't figure out what to do here...

    return $new_string;
}

$result = placeNumberInString(aBcDEFghIJKlmNo, 12345);

echo $result;

3

Answers


  1. You can split the string at random index starting at the last index and insert the number

    function placeNumberInString($string, $number){
        $new_string = $string;
        
        $numberArray = str_split((string)$number);
        
        $index = 0;
    
        foreach ($numberArray as $value) {
            $index = rand($index, strlen($new_string));
            
            $begin = substr($new_string, 0, $index + 1);
            $end = substr($new_string, $index + 1);
            
            $new_string = $begin . $value . $end;
        }
    
        return $new_string;
    }
    
    $result = placeNumberInString("aBcDEFghIJKlmNo", 12345);
    
    echo $result;
    
    Login or Signup to reply.
  2. This is essentially a single iteration of a classic riffle shuffle between a aBcDEFghIJKlmNo stack and a 12345 stack. Use str_split() to split each stack into arrays, so that you have this:

    $one = ["a","B","c","D","E","F","g","h","I","J","K","l","m","N","o"];
    $two = ["1", "2", "3", "4", "5"];
    

    Then implement the shuffle on those two arrays:

    • Pick a stack randomly, but weighted by the number of elements in that stack. This ensures you get an even distribution when the stacks are different sizes.
    • Take one element from the front/top of that stack and add it to the end of the new merged stack.
    • Repeat until there are no elements left.

    Something like:

    function riffle(string $one, string $two): string
    {
      $new = '';
      $tot = strlen($one . $two);
      $from = [str_split($one), str_split($two)];
      while (array_filter($from)) {
        $new .= array_shift($from[lcg_value() <= count($from[0]) / $tot-- ? 0 : 1]);
      }
      return $new;
    }
    
    Login or Signup to reply.
  3. If you want to preserve the order of the digits in the number, you could just build up the new string a bit at a time.

    $numberAsString = (string) $number;
    $stringLength = strlen($string);
    $numberStringLength = strlen($numberAsString);
    
    $s = 0;
    $i = 0;
    while (($s < $stringLength) && ($i < $numberStringLength)) {
        if (random_int(0, 1)) {
            $newString .= $string[$s];
            $s++;
        } else {
            $newString .= $numberAsString[$i];
            $i++;
        }
    }
    if ($s < $stringLength) {
        $newString .= substr($string, $s);
    } else {
        $newString .= substr($numberAsString, $i);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search