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

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

Related

converting number from higher to lower [duplicate]

This question already has answers here:
PHP: How to sort the characters in a string?
(5 answers)
Closed 2 years ago.
we are trying to reorder the number
for example
5695479 to 9976554
48932 to 98432
means all bigger numbers then smaller number.
i was searching for some inbuilt function in php, we found sort function can do with array.
$numbers=array(4,6,2,22,11);
sort($numbers);
function my_sort($a,$b)
{
if ($a==$b) return 0;
return ($a<$b)?-1:1;
}
$a=array(4,2,8,6);
usort($a,"my_sort");
i have searched lot but i could not found any inbuilt functions.
There is no specific in-built function for this. However, you can use more than 1 inbuilt function to accomplish your task.
You can convert the integer to string usingstrval.
Now, split the string by each digit to get an array of integers.
Apply rsort() to sort them in descending order.
Implode() them back to get the number you desire.
Snippet:
<?php
$str = strval(5695479);
$nums = str_split($str);
rsort($nums);
echo implode("",$nums);
Another alterantive is to use counting sort for digits. Since digits will always be between 0-9, collect their count and loop from 9 to 0 and get the new number. This method would be faster than the first method if you have the number in string format with huge lengths.
Snippet:
<?php
$num = 48932; // if number is in string format, loop char by char using for loop
$count = [];
while($num > 0){
if(!isset($count[$num % 10])) $count[$num % 10] = 0;
$count[$num % 10]++;
$num = intval($num / 10);
}
$new_num = 0;
for($i = 9; $i >=0; --$i){
if(!isset($count[$i])) continue;
while($count[$i]-- > 0) $new_num = $new_num * 10 + $i; // you would rather concatenate here incase of string.
}
echo $new_num;

Split a number by 13 digits using php [duplicate]

This question already has answers here:
Break long string into pieces php
(5 answers)
Closed 3 years ago.
I want to make a program which splits a long number into pieces of 13 digited number such that I can loop for every 13 digits just using php.
$number = 012345678901230123456789123
Should output
0123456789123
0123456789123
And it should be for any large number having the number of digit multiple of 13.It looks about looping and algorithm but I want to make it as short as possible and I have doubts on how to do it. So I am just asking about the main concept.
The most dynamic solution is probably to use array_functions on the string.
So str_split to make it array then chunk it in size 13 and implode the arrays.
$number = "012345678901230123456789123";
$arr = array_chunk(str_split($number), 13);
foreach($arr as &$val){
$val = implode($val);
}
https://3v4l.org/LsNFt
You can create a function where you can use your string and size as parameter and return an array of strings of the desired length:
function splitString($str, $packetSize) {
$output = [];
$size = strlen($str);
for ($i = 0; $i < $size; $i += $packetSize) {
if ($i + $packetSize < $size) {
$output[]= substr($str, $i, $packetSize);
} else {
$output[]=substr($str, $i);
}
}
return $output;
}

Generate random numbers [duplicate]

This question already has answers here:
Generating UNIQUE Random Numbers within a range
(14 answers)
Closed 7 years ago.
I am trying to find a solution in PHP that can generate three random numbers.
At the moment I have this that generates a random number that is different from $randNum;
The numbers need to be different from each other and also different from the variable $randNum
Thank you
$wrong = $randNum;
while ($wrong == $randNum) {
$wrong = rand(0,$max - 1);
}
<?php
$numbers = [];
for($i = 0; $i < 10; $i++){
$number = rand (1,15);
while (in_array($number, $numbers)){
$number = rand (1,15);
}
$numbers[] = $number;
}
echo '<pre>';
print_r($numbers);
echo '</pre>';
This function generates unique 10 random numbers, range from 1-15 you can easy change this script to your needs.

Random number thats not in array [duplicate]

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..

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