Random integer with conditions - php

I have a PHP script where I have an array of integers, let's say $forbidden.
I want to get a random integer from 1 to 400 that is not in $forbidden.
Of course, I don't want any loop which breaks when rand gives a working result. I'd like something more effective.
How do you do this ?

Place all forbidden numbers in an array, and use array_diff from range(1,400). You'll get an array of allowed numbers, pick a random one with array_rand().
<?php
$forbidden = array(2, 3, 6, 8);
$complete = range(1,10);
$allowed = array_diff($complete, $forbidden);
echo $allowed[array_rand($allowed)];
This way you're removing the excluded numbers from the selection set, and nullifying the need for a loop :)

Produce an array of the allowed numbers. Find out the number in this array. Select one of those randomly.

Related

Creating Arrays of test data in PHP

Firstly, I'm still a beginner to PHP so my terminology may be a bit wrong - please let me know and I'll amend the question.
Task:
I have a function which I'm looking to test to see how long it takes to run at large scale. I need to pass it data in the following format:
$data = [
[ 'A', 'B', 'C', 'D' ],
[ 'C', 'B' ],
[ 'C', 'B' ],
];
As you can see, the number of items in an array can vary - although they are drawn from an overall set (range of integers or letters).
For my testing purposes, I'd like to be able to change the number of items in each nested array.
I also need to be able to change how many arrays are created.
Example tests I'd like to perform
e.g.
Run one test with a small number of arrays, but a large amount of
data within each.
Run a second test with a large number of arrays, but
a small amount of data in each
A third with huge numbers of items
and arrays.
The story so far
I was Googling and know I could use range() to create an array that count sequentially (or with a certain step). But I have to set the upper and lower bounds for each array.
I figure I could use a do.. while loop to add X number of arrays within $data, but I'm not sure how I can vary the amount of data within each array.
For the function to work, I need there to be either a letter or integer repeated. In other words: I couldn't have the first array count from 1-10, the next 11-21. It's as if all the data is drawn from the pool of integers 1-10,000,000.
Bonus points if the data can be randomized in order in each array.
Really appreciate any guidance and pointers on what to use / research - I'm sure this is a totally n00b question.
Many thanks in advance.
Generate a random range:
range(mt_rand(0, 100), mt_rand(101, 1000))
Generate an array of letters from a range (65 = A, 90 = Z):
array_map('chr', range(65, 90))
Generate a random order:
$data = range(..);
shuffle($data);
Take a random slice of an array:
$data = range(..);
$data = array_slice($data, mt_rand(0, count($data) - 1), mt_rand(1, count($data)));
Generate arrays of random length:
for ($i = 0, $length = mt_rand(0, 100); $i < $length; $i++) {
$data[] = ..;
}
You can nest two of those to generate randomly long arrays of randomly long arrays.
Now combine all these techniques as needed to spit out the kind of test data you want.

filling an array with array_pad

I am currently working on a site where I have an array that must contain 8 values.
I generate a random number and write it into my array, after that i would liek to check if this number was infact 8 character long. If this was not the case it should be filled with leading zero's.
Here is the code i am using
$number=rand(0,255);
// convert the number to binary and store it as an array
$states=str_split(decbin($number),1);
echo '<pre>'.print_r($states,true).'</pre>';
// in case the number is not 8 bit long make it an 8 bit number using array_pad
if(count($states)<8){
$states = array_pad($states,count($states)-8,"0");
}
The problem is now that it never fills up the array even if the array only consists of 3 or 4 entrys.
Thanks for the help.
Edit :Thanks to everyone for awnsering so quickly the solution provided by Suresh Kamrushi is working.
instead of
$states = array_pad($states,count($states)-8,"0");
Try like this:
$number=rand(0,255);
// convert the number to binary and store it as an array
$states=str_split(decbin($number),1);
echo '<pre>'.print_r($states,true).'</pre>';
// in case the number is not 8 bit long make it an 8 bit number using array_pad
if(count($states)<8){
$states = array_pad($states,8,"0");
}
print_r($states);
PHP fiddle: http://phpfiddle.org/main/code/a1d-m97
If I understand correctly you don't need count($states) - 8:
$states = array_pad($states, -8, "0");
Which will pad the array to a size of 8, with leading zeroes
For array_pad the second argument is the size you want the array to be, not the number of items you want to add to it.
So just do:
if(count($states)<8){
$states = array_pad($states,8,"0");
}
Or, as array_pad has no effect if your array is already big enough, you don't even need the if(count($states)<8) part.

Filling an array with numbers sequentially

I have a number (e.g. 6) that is dynamically generated and I would like to fill an array with the numbers 1 through the dynamically generated number (in this example, 6):
array(1, 2, 3, 4, 5, 6);
The only way I know to do this at the moment is by using a for loop, but I'm wondering if there's a better way, something similar to array_fill. I looked at array_fill, but it doesn't look like it will take a number and increment it for a set number of times.
Use range:
$arr = range(1,6);
// Returns an array of elements from start to limit, inclusive.
This is what you are looking for:
range(1, 6)

array_rand() array to string?

I have an array, such like:
$hex = array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
I want to return 6 random elements as a string (eg. 1a3564):
$random_color = array_rand($hex,6);
I thought imploding $random_color would do the trick:
echo implode($random_color);
But array_rand() stores positions of elements in parent array, not this array elements, so I get something like:
259111213 instead of 259bcd.
I know this does exactly what I want:
echo $hex[$random_color[0]];
echo $hex[$random_color[1]];
echo $hex[$random_color[2]];
echo $hex[$random_color[3]];
echo $hex[$random_color[4]];
echo $hex[$random_color[5]];
But:
is there any way to store array elements within array_rand()? Why it stores elements' positions instead of elements in the first place?
what's the best way to do what I want to achieve?
why does array_rand() NEVER choose a letter as the first element, and almost never as the second/third (99% of generated colors look like 11111a 12345c 123456)?
Random colors should be generated in simplier way:
printf('%02x%02x%02x',mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
or
printf('%06x',mt_rand(0,16777215));
If you need to save color to variable, use sprintf instead of printf
Since the items are all different, you can turn them into keys rather than values, then use array_rand on the result:
implode('', array_rand(array_flip($hex), 6));
However, there may be a better way of achieving your overall goal. For example, if the overall goal allows for repetitions of digits, simply generate a random number from 0 through 0xFFFFFF and convert to a hex string:
dechex(mt_rand(0, 0xFFFFFF));
Why it stores elements' positions instead of elements in the first place?
From the manual page:
This is done so that you can pick random keys as well as values out of the array.
why does array_rand() NEVER choose a letter as the first element, and almost never as the second/third (99% of generated colors look like 11111a 12345c 123456)?
array_rand uses rand (php_rand, in the C source). Depending on your system, php_rand is rand, random or lrand48. rand is a particularly poor random number generator.
array_rand() returns the keys of the randomly picked elements (see manual, section Return Values).
In order for it to work as expected, use array_flip() to retrieve the keys:
$random_color = array_rand(array_flip($hex), 6);
As for the "strange" results where there are almost no letters first elements, IDEOne and my server seem to reproduce these findings. A local machine running in my office (still running Debian etch / PHP 5.2.9) seems to disagree and evenly distribute elements from $hex... Seems to be a PHP version thing?
you are close try this:
$hex = array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
shuffle($hex);
echo sub_str(implode('',$hex),0,6);
If you don't need to maintain the order of the $hex array, you could substitute this with shuffle(). Something like this (codepad example):
<?php
$hex = array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
shuffle($hex);
echo implode(array_slice($hex, 0, 6));
If you just want a random string of hex digits, you could also do something like
substr(md5(time()),-6);
or
substr(md5(uniqid()),-6);
You would get similar results without having to mess with the array.
is there any way to store array elements within array_rand()? Why it
stores elements' positions instead of elements in the first place?
According to array_rand documentation, it returns the array 'keys', not the 'values'. Since your array is not an associative array, the keys are numbers. You'd need to do (untested):
$result = "";
$random_color = array_rand($hex, 6);
foreach ($random_color as $randomIndex) {
$result = $result . $hex[$randomIndex];
}
Don't use array shuffle or array_rand because elements cannot repeat with that approach. That's not what you are trying to do.
what's the best way to do what I want to achieve?
If you want to generate a random color, you can use:
$color = '';
while(strlen($c) < 6) {
$color .= sprintf("%02X", mt_rand(0, 255));
}
why does array_rand() NEVER choose a letter as the first element, and
almost never as the second/third (99% of generated colors look like
11111a 12345c 123456)?
You may need to initialize the random numbers generator, but this is just a guess (see Timur's comment to this answer).
mt_srand((double)microtime()*1000000);

How to sort each numerical value in a number?

I am making a PHP login/register form and to confirm whether someone is actually human and not a bot I am generating a random value that has to be written in a certain way.
For example:
Please write the following number in an increasing manner: 34745
The user should write 34457 and only then will the confirmation work.
The thing is I know how to use the rand() function, that's how I generate the number. But the problem is I do not know how to make PHP sort the generated number's numerical values (for ex.: 64348 -> 34468).
How do I do this? I hope there is a single function for that, as I've seen numerous ways to sort arrays and since they have indexes I only suppose that it should be possible to sort a number's values.
<?php
$number = str_split("647214");
sort($number);
$number = implode($number);
echo $number;
?>
Demo: http://codepad.viper-7.com/RepImd
Instead of using an integer to hold the complete number you could create an array of size n (n is the number of digits). Iterate over the array and use rand() to create random numbers from 0-9 in each position of the array. Now you have an array which can be sorted by using standard sort functions.
I don't think it has single function, but you can make this.
$num = 34745;
$chars = preg_split('/ /', $num, -1, PREG_SPLIT_OFFSET_CAPTURE);
sort($chars);
$res = implode("", $chars);
echo $res;
I didn't tested this, but I hope it works!

Categories