Random number thats not in array [duplicate] - php

This question already has an answer here:
PHP how to get a random number that is different from values of an array
(1 answer)
Closed 7 years ago.
I have an array of numbers and I need to make a random number then check if that number is not in the array, If it is make another random number and then check that number to see if its in the array.
example.
array = 1, 2, 4, 5, 7
rand(1, 7) = 3 or 6
if rand(1, 7) = 1, 2, 4, 5 or 7 it would run again until it returned 3 or 6.
anyone know how to do this in php?

You may simply generate a random number and check if it is already in the array
$in = [1, 4, 7, 9];
do {
$rand = rand($min, $max);
} while(in_array($rand, $in));
echo $rand, ' is random, but not in the input array';
The above code generates a random integer that is insides the bounds defined in $min and $max. If the value already exists inside the array a new random value is fetched and compared to the input array.
Note: While the above is the minimal working code you may create an endless loop if your input array contains all possible values(Thanks #Action Dan). You didn't state in your question whether this is possible or not. If it is possible you need to work around this. Either by limiting the the maximum tries or validating the input array before and issuing an error message or increasing the 2nd parameter of rand.
Example(validating, only recommended for smaller arrays):
$in = [1,2,3,4,5];
$min = 1;
$max = 5;
if(range($min, $max) === $in) {
echo 'No possible value in range';
exit;
}
// code from above

<?php
$numbers = array(1,2,3,4,5,6,7);
$rand = rand(1,10);
if (in_array($rand, $numbers))
{
echo "Match found";
}
else
{
echo "Match not found";
}
echo "<br />" . $rand;
?>
In this sample I had $rand intentionally have more than 7, just to make sure the code is working well and "Match not found" is printed..
in_array() function checks if the value of $rand exists in $numbers if true.. prints "Match found" if not prints "Match not found".
Hope this helps..

Related

how to read for a certain symbol in a string [duplicate]

This question already has answers here:
What is the most efficient way to count all the occurrences of a specific character in a PHP string?
(4 answers)
Closed 5 years ago.
I am trying to separate 2 symbols from a string and then
count how many of these symbols there are.
So if i had : 1110001110000
Then it should find that there are 6= 1's and 7= 0's
So This is what I have tried:
Essentially what I need, is to read the string indexes in code would be string[$i] then IF there is a 1 or a 0 count it.
I tried using a for-loop
for ($i=0; $i < $getInput[$i] ; $i++) {
if ($getInput[$i] == 1) {
echo "ONE";
} elseif ($getInput[$i] == 0) {
echo "ZERO";
}
}
Here im trying to echo out ONE for everytime ther is a 1 and ZERO for everytime theres a zero.
$counter = 0;
foreach ($getInput as $key) {
echo $key;
}
here i tried to utilize a foreach, here I am not really declaring to see for One index, i tried putting a for each in a for but needless to say, it didn't work.
Using substr_count, you can do this in a fairly straightforward way:
echo substr_count("1110001110000", '1'); //Echos 6
echo substr_count("1110001110000", '0'); //Echos 7
Substr_count.
http://php.net/manual/en/function.substr-count.php
$str = "1110001110000";
Echo "there is " .substr_count($str, "0") ." zeros \n";
Echo "there is " .substr_count($str, "1") ." ones \n";
https://3v4l.org/BQEiR
If you want to output it as your code implies (one one one zero) you can use numberformatter.
Here I split the string to an array and loop through it and output the spellout of each number.
$str = "1110001110000";
$arr = str_split($str);
$nf = new NumberFormatter("en", NumberFormatter::SPELLOUT);
Foreach($arr as $numb){
echo $nf->format($numb) . " ";
}
Output:
one one one zero zero zero one one one zero zero zero zero
https://3v4l.org/nHX59

How to randomly generate a number from a range of numbers but exclude some numbers? [duplicate]

This question already has answers here:
PHP rand() exclude certain numbers
(10 answers)
Closed 6 years ago.
How would I generate a random number from a range of numbers between 1 and 10 while excluding an array of numbers e.g. 4,5,6.
$exclude = array(4,5,6);
The following code allows to generate random numbers within a range however only for a single number and not an array of numbers
function randnumber() {
do {
$numb = rand(1,10);
} while ($varr == 4);
return $numb;
}
Create a loop that iterates until a generated random number using rand function is not in array. If the generated number is found in array, again another random number is generated.
do {
$number = rand(1,10);
} while(in_array($number, array(4,5,6)));
echo $number;
or
while(in_array(($number = rand(1,10)), array(4,5,6)));
echo $number;
You can use it like a function too:
<?php
function randomNo($min,$max,$arr) {
while(in_array(($number = rand($min,$max)), $arr));
return $number;
}
echo randomNo(1,10,array(4,5,6));
The above function, does the same process, in addition, you can reuse the code. It gets minimum and maximum number and the array of values to exclude.
Finally,
without loop, but with recursive function. The function generates a random number and returns if it is not found in the exclude array:
function randomExclude($min, $max, $exclude = array()) {
$number = rand($min, $max);
return in_array($number, $exclude) ? randomExclude($min, $max, $exclude) : $number;
}
echo randomExclude(1,10,array(4,5,6));
<?php
$exclude = array(4,5,6); // The integers to excluded
do
{
$x = rand(1, 10); // Generate a random integer between 1 and 10
}while(in_array($x, $exclude)); // If we hit something to exclude, try again
echo $x; // A random integer not excluded
?>
It would be wise to check if not all inputs are excluded to avoid infinite loops
You can simply do this, using array functions like this:
function my_rand($min, $max, array $exclude = array())
{
$range = array_diff(range($min, $max), $exclude);
array_shuffle($range);
return array_shift($range);
}
Some time ago I also wanted to become rid of these nasty little while loops. Reduced to fit your version of the problem, my approach would be to:
first generate a random number which in range (10 - 3) to indicate the position of the number to be generated in the hypothetical list of numbers in the desired range excluding {4,5,6}
second increment this value by the lower range (1)
third increment by 1 for every number in the set {4,5,6} it is equal to or greather (in order from the smallest to the highest number in that set)
So, all in all I'd basically stretch and blurr the hypothetical set of numbers the generated random value can be to fit into the possible outcomes.
$total = range(0,10);
$exclude = range(4,6);
$include = array_diff($total, $exclude);
print_r (array_rand($include));

How to generate a random number with fixed length only with 0's and 1's and a fixed amount of 1's?

I did some research, but didn't found any solution for my question.
What I want to archive:
Generate a random number out of 0's ($min) and 1's ($max), but with a fixed amount ($many) of 1's in the random number. The random number should have a length of 6 as in my while loop (while($xLoop <= 6)).
Here is my current code:
$min = 0;
$max = 1;
$many = 3;
$xLoop = 1;
while($xLoop <= 6) {
$nRand = mt_rand($min,$max);
if($nRand == 1){ //if random number comes out number 1
$many--; // Prevent number 1 more then $many...
//Do something...
}else{ //if random number comes out not number 1
//Do something and still looping until get 6 times
}
echo $nRand.' - '.$many.'</br>'; //For debugin... i want to see how many number 1 comes out.
$xLoop++;
}
It will loop 6 times, so we have a random number of the length 6, but I want a fixed amount of 1's in my random number, which is $many (here 3). And the rest filled with 0's until we reach the length 6.
How can I fix this code? Or is there a simpler way?
This should work for you:
No need for a loop. Just first fill an array with 1's $many times. Then array_merge() the array with the 0's which you fill up until $length elements.
At the end just shuffle() the array and implode() it to print it
<?php
$min = 0;
$max = 1;
$many = 3;
$length = 6;
$arr = array_fill(0, $many, $min);
$arr = array_merge($arr, array_fill($many, $length-$many, $max));
shuffle($arr);
echo implode("", $arr);
?>
possible output:
011010

How to make sure that random number will not duplicating? [duplicate]

This question already has answers here:
Generating UNIQUE Random Numbers within a range
(14 answers)
Closed 9 years ago.
I tried to use rand() to make it my unique id in database. But how to make sure that this random number will not be duplicated?
<?php
$num = '';
for ($i = 0; $i < 9; $i++)
$num .= mt_rand(0, 9);
echo '<input name="counter" value="'.$num.'">';
?>
In case you want to insert unique values in the database table (that is how I understood you), it is better to create unique index in the database (which ensures that no duplicate entries are in table for the following column. In case of php, check that duplicate value does not already exist in your array.
<?php
$unique = array();
while( count($unique) < 9)
{
$num = mt_rand(0, 9);
if( isset($unique[$num]) == false )
$unique[$num] = true;
}
print_r($unique);
?>
It's better if you do this way.
First get the range you want with range()
Then you shuffle the array so you can get it in a random order.
Now if you want only 5, you can use array_slice.
$range = range(1, 20);
shuffle($range);
$random = array_slice($range, 0, 5);
print_r($random);
Working example: example

Awkward criteria when generating random sequence

What I need to do to generate a sequence of non-repeating integers within a given range that meets the specific criteria that I have?
Here are the criteria:
Use only the numbers between 1 and MAX (let's say 9).
Numbers cannot repeat within the sequence except:
2a. Two of the first 5 numbers from the sequence must be repeated.
2b. These two numbers must be repeated at random points within the last 5 places in the final sequence (the last 5 includes the repeats).
For example:
SET: 1,2,3,4,5,6,7,8,9
Random Sequence (with repeats):
2,4,6,9,3,1,5,2,8,7,3
r, , , ,r, , ,x, , ,x
Here I have indicated the numbers that were randomly selected to be repeated (out of the first 5 in the random sequence) with an r and the insertion points where they were randomly placed (into the last 5 of the final sequence) with an x.
Any help in figuring this out is much appreciated. Actual use will be a bit more complicated than this, but I know what I will need to do once I can get this far.
Edit
To clarify a little more, I have 1-20, and I need a 22 digit random sequence. Every number must be used, two will be used twice as discussed in my original post. I chose 10 above to simplify a little. I should be able to adapt the logic you've all given.
I assume when you say "non-repeating" you mean "distinct" (unique) as opposed to "eventually becomes periodic" (as in "the digits of pi do not repeat")
Generate n distinct integers in your range.
Pick two from the first 5. Call these a and b.
Remove the last 3 from the list.
Insert a at position 0, 1, 2, or 3 in the sublist.
Insert b at position 0, 1, 2, 3, or 4 in the sublist.
Add the sublist back to the end of the list.
Removal of the sublist is not necessary but makes it easier to conceptualize.
Not obvious what to do if n+2 is less than 10. In particular, this algorithm may crash for n < 5 and return the wrong result for n=7.
If I understand you correctly, you have 1 to N random numbers that must be used in a 10-set permutation with some specific criteria about repeats. In php, I suggest this (not counting php-internals) O(n) solution:
//Generate a full list of keys
$source = range(1, MAX);
//NOTE: if MAX < 10, you must pad the array
//Get a random group of 10 of the keys
$input = array_rand(array_flip($source), 10);
//Shuffle (can be done later as well; this is the randomization).
//array_rand() does not change order.
shuffle($input);
//Select the first of 5 that must be repeated in the last 5
$one = rand(0, 4);
$onev = $input[$one];
//Remove this array key to prevent collisions with the second of 5
$input = array_diff($input, array($onev));
//Select a random index in the last 5 to be replaced with $one
$rep = rand(5, 9);
$repv = $input[$rep];
//Remove this array key to prevent collisions with the other to-be-replaced
$input = array_diff($input, array($repv));
//Acquire the new keys list of input now that two elements have been removed
$keys = array_slice(array_keys($input), 0, 3);
//Select the second-of-5 to replace in the last 5. No worry of collision now.
$two = array_rand($keys, 1);
$two = $keys[$two];
//Select the second from the last-of-5 to be replaced by $two
//No worry of collision because the other index is removed.
$keys = array_slice(array_keys($input), 4, 8);
$rept = array_rand($keys, 1);
$rept = $keys[$rept];
//Replace one of the last-of-five with one of the first-of-five
$input[$rept] = $input[$two];
//Restore removed keys as well as perform replacement of other last-of-five
$input[$one] = $onev;
$input[$rep] = $onev;
//re-randomize based on shuffle
ksort($input);
No loops, no conditionals.
A word of warning on this solution. I wouldn't use it for a large set of numbers. If I were doing this same solution for a much larger set, I would use array_splice to drop chosen members from the array. As you get a much larger space, finding an unused number in your range becomes quite expensive, and demands a better solution than the brute force method below.
This will build half of your target set. You will call it twice, once for each half.
function build_half($min, $max, $num_elements, $arr = array() ){
while( count($arr) <= $num_elements)
{
$candidate = rand($min, $max);
if( !in_array($candidate, $arr))
{
array_push($arr, $candidate);
}
}
return $arr;
}
This will grab $this_many elements from the array.
function random_grab($arr, $this_many){ // don't try this on the subway
$nums_to_repeat = array();
// catch some edge cases...
if( $this_many > count($arr) )
{
return FALSE;
}
else if( $this_many == count($arr) )
{
return shuffle($arr);
}
while( count($nums_to_repeat) <= $this_many)
{
$rand_key = rand(0, count($arr) - 1);
if( ! in_array($arr[$rand_key], $nums_to_repeat))
{
array_push($nums_to_repeat, $arr[$rand_key]);
}
}
return $nums_to_repeat;
}
This is a fairly specialized case, but could be made more general by allowing the offset floor and ceiling to be passed in as parameters. For your problem they would be 5 and 9, so we just derive them directly.
function random_insert_2nd_half($target, $source){
$offsets_consumed = array();
$num_elements = count($target);
while( count($source) > 0 )
{
$offset = rand( ($num_elements/2), $num_elements - 1);
if( ! in_array( $offset, $offsets_consumed)
{
$arr[$offset] = array_pop($nums_to_repeat);
}
}
}
Ok so after having done all that, let's put it to work.
// Generate the first half of the array
$my_array = $repeated_nums = array();
$my_array = build_half(1, 10, 5);
// then grab the 2 random numbers from that first half.
$repeated_nums = random_grab($my_array, 2);
// So now we have our random numbers and can build the 2nd half of the array.
// we'll just repeat the call to the first function.
$my_array = build_half(1, 10, 5, $my_array);
// Then swap out two of the values in the second half.
$my_array = random_insert_2nd_half($my_array, $repeated_nums);
// at this point $my_array should match what you are looking for.
Hope this gets you on your way:
$max = 20; // max value
$repeats = 2; // numbers to be repeated
$nums = range(1, $max);
shuffle($nums);
$halfPoint = ceil($max / 2);
$firstHalf = array_slice($nums, 0, $halfPoint);
$repeaters = array_intersect_key($firstHalf, array_flip(array_rand($firstHalf, $repeats)));
$secondHalf = array_merge(array_slice($nums, $halfPoint), $repeaters);
shuffle($secondHalf);
$result = array_merge($firstHalf, $secondHalf);
var_dump(join(',', $result));
To generate distinct numbers within a range you can use something like this:
$arr_num = array();
while(count($arr_num)<=7)
{
$num = rand(1, 9);
if (!in_array($num, $arr_num))
{
$arr_num[] = $num;
}
}
$arr_num now has 8 distinct elements. Pick five elements of the array:
for ($i=0; $i<=4; $i+=1)
{
$new_arr[$i] = $arr_num[$i];
}
Now pick two numbers from $new_arr numbers:
$r1 = array_rand($new_arr);
$r2 = array_rand($new_arr);
Now you can insert these numbers into the original array at two of the last random positions. Hope it helped!
$max = 15;
$array = array(1, $max);
for($x = 1; $x <= $max; $x++)
{ $array[$x] = rand(1, $max); }
$firstDup = $array[rand(1,5)];
$secondDup = $firstDup;
do { $firstDup = $array[rand(1,5)];
} while($firstDup == $secondDup);
do { $array[rand($max-5,$max)] = $firstDup;
} while(!in_array($firstDup,array_slice($array,$max-5,5)));
do { $array[rand($max-5,$max)] = $secondDup;
} while(!in_array($secondDup,array_slice($array,$max-5,5)));

Categories