generate random number from an array - php

in mock test, i store id of questions in an array and i want when test start then it generate radomly id's from this array. when id is less then 10 then it generate correct number but when it store greater then 10 like 20,21,22.. then it also generate also number form 1-10. i want it generate random number from number which store in this array. thnax..
$ids= array('20','21','22','23','24','25','26','27','28','29','30','31','32',);
$getIds=mysql_query("select * from mock_test_question where status='1' and question_level='FINAL' ") or die(mysql_error());
while($data=mysql_fetch_array($getIds))
{
array_push($ids, $data['id']);
}
print_r($ids);
echo "</br>";
$rand_keys = array_rand($ids,5);
$_SESSION['quesid']=$rand_keys;
print_r($rand_keys);

array_rand returns the KEYS (array positions) not the actual values. To get the values:
echo $ids[$rand_keys];

This should give you a random number
$randomValues = array('20','21','22','23','24','25','26','27','28','29','30','31','32');
$randomValuesIndex = array_rand($randomValues, 1);
$randomValue = $randomValues[$randomValuesIndex];
echo $randomValue."\n";
An example loop that generates random numbers
$randomValues = array('20','21','22','23','24','25','26','27','28','29','30','31','32');
for ($i = 1; $i < 30; $i++)
{
$randomValuesIndex = array_rand($randomValues, 1);
$randomValue = $randomValues[$randomValuesIndex];
echo $randomValue."\n";
}

$count = count($ids) - 1; # note that its -1 because array keys start from 0
echo $ids[rand(0,$count)];
here is a fast way to get random element from array
P.S>
Here is complete code with generate of numbers and usage..
$ids = array();
for($i=20;$i<=32;$i++){ $ids[]=$i; }
$count = count($ids) - 1;
echo $ids[rand(0,$count)];
echo $ids[rand(0,$count)];
echo $ids[rand(0,$count)];

Related

how to get array random from object?

I tried to make array from random item object to get 2 items. I used array_rand() but the output is array_rand() expects parameter 1 to be array, integer given and Trying to get property of non-object
My code is for get random item is :
$k=2;
$centroid = array();
for($i=0; $i<$k; $i++){
$centroid[] = new DataSet($table[array_rand($i)]->sig_class_id,$table[array_rand($i)]->sig_priority);
}
Get data from
$query = mysqli_query($conn,"SELECT sig_class_id, sig_priority FROM coba");
$table=array();
while ($row = mysqli_fetch_object($query)) {
$table[] = new DataSet($row->sig_class_id, $row->sig_priority);
}
and class DataSet is
class DataSet{
public $sig_class_id;
public $sig_priority;
function __construct($sig_class_id, $sig_priority){
$this->sig_class_id = $sig_class_id;
$this->sig_priority = $sig_priority;
}
}
any thought?
I think you are in wrong logic. Instead, you should get a random number and get random number related array. Try below code!
$random = 0;
$centroid = array();
for($i=0; $i=2; $i++){
$random = rand();
$centroid[] = new DataSet($table[$random]->sig_class_id,$table[$random]->sig_priority);
}
== Edit 1 ==
Tip 1 : You can also use mt_rand() function produces a better random value, and is 4 times faster than rand().
Tip 2 : If you want a random integer between 10 and 100 (inclusive), use rand (10,100).

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

Find the matched value of an array with a given value

I have an array of value series like:
$series = [100,300,500,800,1000,3000,5000,10000,15000,20000];
Another value getting from DB like:
$point = $data[‘earned_point’];
I need the highest match from the series. such as I got a value from db (1500) the highest match of the value is 1000 in the series, so I need to get the $series[4] and make it
$reward = $series[4] * 0.1;
I'll run it in a loop to do it for all the values got from DB.
I'm posting alternate code as the accepted answer while is correct can be very inefficient if you are working with a large array.
<?php
function computeReward($series, $point, $percent = 0.1){
arsort($series); // sort the series in reverse so we can pass any array and the highest number will be the first because we are looking for a number lower or equal to our point
foreach($series as $min_point){
if($min_point <= $point){
return $min_point * $percent; // return the min_point * the percentage, this stops the loop there for being more efficient
}
}
}
$series = [100,300,500,800,1000,3000,5000,10000,15000,20000];
$point = $data['earned_point'];
$reward = computeReward($series, $point);
?>
Do you mean you want to get which highest $series item is equal or less than $point ?
<?php
$series = [100,300,500,800,1000,3000,5000,10000,15000,20000];
$point = $data['earned_point'];
foreach ($series as $min_point) {
if ($point >= $min_point) {
$matched_min_point = $min_point;
}
}
$reward = $matched_min_point*0.1;
Let me know if this works for you

How to increment number after letter in PHP

I'm looking to increment a number after a certain letter.
I have a list of own Ids and i would like to increment it without write it manually each time i add a new id.
$ids = array('303.L1', '303.L2', '303.L3', '303.L4');
so i use the END() function to extract the last id from this array.
this is what i've tried but i cannot get a result.
$i = 0;
while($i <= count($ids)){
$i++;
$new_increment_id = 1;
$final_increment = end($last_id) + $new_increment_id;
}
echo $final_increment;
New method, but it is adding me double dot between number and letter.
$i = 0;
while($i <= count($ids)){
$i++;
$chars = preg_split("/[0-9]+/", end($ids));
$nums = preg_split("/[a-zA-Z]+/", end($ids));
$increment = $nums[1] + 1;
$final_increment = $nums[0].$chars[1].$increment;
}
//i will use this id to be inserted to database as id:
echo $final_increment;
Is there another way to increment the last number after L ?
Any help is appreciated.
If you don't want a predefined list, but you want a defined number of ids returned in an $ids variable u can use the following code
<?php
$i = 0;
$number_of_ids = 4;
$id_prefix = "303.L";
$ids = array();
while($i < $number_of_ids){
$ids[] = $id_prefix . (++$i); // adds prefix and number to array ids.
}
var_dump($ids);
// will output '303.L1', '303.L2', '303.L3', '303.L4'
?>
I'm a bit confused because you say "without write it manually". But I think I have a solution:
$ids = array('303.L1', '303.L2', '303.L3', '303.L4');
$i = 0;
while($i <= count($ids)){
++$i;
//Adding a new item to that array
$ids[] = "303.L" . $i;
}
This would increment just that LAST number, starting at zero. If you wanted to continue where you left off, that'd be simple too. Just take $i = 0; and replace with:
//Grab last item in array
$current_index = $ids[count($ids) - 1];
//Separates the string (i.e. '303.L1') into an array of ['303', '1']
$exploded_id = explode('.L', $current_index);
//Then we just grab the second item in the array (index 1)
$i = $exploded_id[1];

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