Split string into 3 random-length parts

Viewed 419

I have a string and I want to split it into 3 random-length parts (without caring about string length is the objective) to get 3 strings.

$mystring = "aHR0cHM6Ly93d3cucGhwLm5ldC9tYW51YWwvZW4vZnVuY3Rpb24uc3RyLXNwbGl0LnBocA==";

When I tried to use str_split(), I always have to manually set the number of character per string.

If I calculate the string length and divide it by 3, sometimes I get non-whole numbers.

$len = strlen($mystring);
$len = $len / 3;
$parts = str_split($mystring, $len);
print_r($parts);
6 Answers

Even if you want random then I assume you still don't want 0 length strings.
I use random values between 1 and string length (minus some, to make sure you don't run out of characters).

$mystring = "aHR0cHM6Ly93d3cucGhwLm5ldC9tYW51YWwvZW4vZnVuY3Rpb24uc3RyLXNwbGl0LnBocA==";

$len=strlen($mystring);
$parts[] = substr($mystring, 0, $l[] = rand(1,$len-5));
$parts[] = substr($mystring, $l[0], $l[] = rand(1,$len-$l[0]-3));
$parts[] = substr($mystring, array_sum($l));

print_r($parts);

The code grabs parts of the string depending on what the previous random value was.
https://3v4l.org/v4nUF

Something like this would do it:

$mystring = "aHR0cHM6Ly93d3cucGhwLm5ldC9tYW51YWwvZW4vZnVuY3Rpb24uc3RyLXNwbGl0LnBocA==";

$part3 = substr($mystring, rand(2,(strlen($mystring)-2)));
$mystring = substr($mystring, 0, (strlen($mystring)-strlen($part3)));

$part2 = substr($mystring, rand(1,(strlen($mystring)-1)));
$mystring = substr($mystring, 0, (strlen($mystring)-strlen($part2)));

$part1 = $mystring;

var_dump($part1, $part2, $part3);

This code would produce results such as:

string(67) "aHR0cHM6Ly93d3cucGhwLm5ldC9tYW51YWwvZW4vZnVuY3Rpb24uc3RyLXNwbGl0LnB"
string(1) "o"
string(4) "cA=="

string(57) "aHR0cHM6Ly93d3cucGhwLm5ldC9tYW51YWwvZW4vZnVuY3Rpb24uc3RyL"
string(5) "XNwbG"
string(10) "l0LnBocA=="

string(31) "aHR0cHM6Ly93d3cucGhwLm5ldC9tYW5"
string(27) "1YWwvZW4vZnVuY3Rpb24uc3RyLX"
string(14) "NwbGl0LnBocA=="

string(5) "aHR0c"
string(23) "HM6Ly93d3cucGhwLm5ldC9t"
string(44) "YW51YWwvZW4vZnVuY3Rpb24uc3RyLXNwbGl0LnBocA=="

A more generic solution could look like this:

function split_random_parts($string, $part_count) {
    $result = [];
    
    for ($i = 0; $i < $part_count - 1; $i++) {
        // Always leave part_count - i characters remaining so that no empty string gets created
        $len = rand(1, strlen($string) - ($part_count - $i));
        $result[] = substr($string, 0, $len);
        $string = substr($string, $len);
    }
    
    $result[] = $string;
    
    return $result;
}

If you need divide to 3 without random length, may you use str_pad like

$str = 'aHR0cHM6Ly93d3cnVuY3Rpb24uc3RyLXNwbGl0LnBocA==';
$divide = 3;
$char = '*'; // that not used in your string

$add = $divide - strlen($str) % $divide;
$total = strlen($str) + $add;

$str = str_pad($str, $total, $char, STR_PAD_LEFT);

//string(48) "**aHR0cHM6Ly93d3cnVuY3Rpb24uc3RyLXNwbGl0LnBocA=="

$result = str_split($str, $total / $divide );

/*array(3) {
  [0]=> string(16) "**aHR0cHM6Ly93d3"
  [1]=> string(16) "cnVuY3Rpb24uc3Ry"
  [2]=> string(16) "LXNwbGl0LnBocA=="
}*/

keep in mind that strip '*' chars before decode

$result = str_replace('*', '', $result);

Demo

I mean you just need to round up the result of length division like:

<?php
$mystring = "The any size string ...";
$len=strlen($mystring);
$chunk=ceil($len/3);

$parts = str_split($mystring , $chunk);
print_r($parts);

Here the fiddle

Because your input string contains no whitespace characters, you can use sscanf() with %s placeholders with explicit substring lengths (for the first two substrings) to explode the string on dynamic points.

Code: (Demo)

$mystring = "aHR0cHM6Ly93d3cucGhwLm5ldC9tYW51YWwvZW4vZnVuY3Rpb24uc3RyLXNwbGl0LnBocA==";

$len = strlen($mystring);
$end_of_first = rand(1, $len - 2);
$end_of_middle = rand(1, $len - $end_of_first - 1);

var_export(sscanf($mystring, "%{$end_of_first}s%{$end_of_middle}s%s"));

For anyone else who might have whitespaces in their input string, you can replace the s with [^~] where the ~ should be a character that is guaranteed to not occur in your string.


For an approach that accommodates a variable number of segments, a decementing loop seems appropriate.

Code: (Demo)

$totalSegments = 4;

$segments = [];
while ($totalSegments) {
    --$totalSegments;
    $segmentLength = rand(1, strlen($mystring) - $totalSegments);
    [$segments[], $mystring] = sscanf($mystring, "%{$segmentLength}s%s");
}
var_export($segments);
Related