4

I was recently given a task to accomplish which i failed. I don't usually ask for logic but today i am compalled to ask.Here is the task.

I am not allowed to use rand() function of php. instead i can use this function.

function getRandom()
{
     return rand(1,5);
}

OK i tried this function but it is bound to return value from 3 to 7.

function getMoreRandom()
{
    $value = getRandom();
    return $value + 2;

}

Now i have to define a php function which can return me random number with the range 1 to 7. How can i do this?

Muhammad Raheel
  • 19,823
  • 7
  • 67
  • 103
  • Is this a homework assignment or something? Can the `getRandom` function not be altered to just use `rand(1, 7)` instead? – Oldskool Jan 25 '13 at 13:16
  • Strange task, but maybe you need something like this: `$value = getRandom(); $shouldAdd = getRandom(); if($shouldAdd >= 3) { return $value + 2; } else { return $value; }` – Viktor S. Jan 25 '13 at 13:19
  • @FAngel: strange task, indeed. But your solution is strange, too. And it's not uniformly distributed, it will return values between 3 and 5 more often than 1, 2, 6 and 7. – Fabian Schmengler Jan 25 '13 at 13:26
  • 2
    You should probably check this out: http://stackoverflow.com/questions/137783/expand-a-random-range-from-15-to-17 – mallix Jan 25 '13 at 13:31
  • this is not a home work recently i gave an interview and they tested my logic by asking this question – Muhammad Raheel Jan 25 '13 at 13:43
  • thanks @mallix but this shows complicated answers. Isn't here any simple solution? – Muhammad Raheel Jan 25 '13 at 13:51
  • It's a complicated problem. And the top answer is quite simple to implement, what more do you want? – Fabian Schmengler Jan 25 '13 at 14:22

6 Answers6

5
function getMoreRandom()
{
    do {
        $temp = 5 * (getRandom() - 1) + getRandom();
    } while ($temp > 21);

    return $temp % 7 + 1;
}
epicdev
  • 922
  • 4
  • 10
4

flov's Answer is correct:

function getMoreRandom()
{
    do {
        $temp = 5 * (getRandom() - 1) + getRandom();
    } while ($temp > 21);

    return $temp % 7 + 1;
}

Testing it with:

$aryResults = array_pad(array(),8,0);
foreach(range(0,100000) as $i) $aryResults[getMoreRandom()]++;
$intSum = array_sum($aryResults);
foreach($aryResults as $intValue => $intCount) printf("Value %d Count %d (%.2f)\n",$intValue,$intCount,$intCount/$intSum);

Produces rectangular distribution

Value 0 Count 0 (0,00)
Value 1 Count 14328 (0,14)
Value 2 Count 14316 (0,14)
Value 3 Count 14185 (0,14)
Value 4 Count 14197 (0,14)
Value 5 Count 14322 (0,14)
Value 6 Count 14361 (0,14)
Value 7 Count 14292 (0,14)

Sorry I did not comment on the answer. Obviously I can't due to my lack of reputation (I'm new here).

2

It's not going to be a uniform distribution (and you don't specify that it needs to be).

For the most simple solution, you don't need to do scaling or loops, you can take your random 1 to 5, and then add on a random 0 to 2;

function getMoreRandom()
{
    return getRandom() + getRandom() % 3;
}

A quick test to see what the distribution looks like:

$results = array_fill(1, 7, 0);

for ($i = 0; $i < 1000000; $i++) {
    $results[rand(1,5) + rand(1,5) % 3]++;
}

var_dump($results);

As stated, not designed to be uniformly random.

array(7) {
  [1]=>
  int(39550) // 4%
  [2]=>
  int(120277) // 12%
  [3]=>
  int(200098) // 20%
  [4]=>
  int(199700) // 20%
  [5]=>
  int(200195) // 20% 
  [6]=>
  int(160200) // 16%
  [7]=>
  int(79980) // 8%
}

Slightly more complicated, and a different method to @flovs (I don't like the way his loop could last forever - hey, such is randomness)

function getMoreRandom()
{
    for (
        $i = 0, $v = 0;
        $i < 7;
        $i++, $v += getRandom()
    );

    return $v % 7 + 1;
}

This produces a uniform distribution

array(7) {
  [1]=>
  int(14397)
  [2]=>
  int(14218)
  [3]=>
  int(14425)
  [4]=>
  int(14116)
  [5]=>
  int(14387)
  [6]=>
  int(14256)
  [7]=>
  int(14201)
}
Leigh
  • 12,859
  • 3
  • 39
  • 60
1

My solution:

<?php

function getRandom()
{
     return rand(1,5);
}

$random_number = getRandom();
$random_number += time();

$random_number = ($random_number % 7) + 1;
m4t1t0
  • 5,669
  • 3
  • 22
  • 30
0

Just for contributing to a nice question, I think that this could be more generic. That means we maybe do not want 1-7 based on rand(1,5) but 3-7 or 1-10 etc etc.

The function works fine for numbers 1-25, as I am using another solution with 2d array.

function getMoreRand($start, $end){
        $restart = $start; //Save $start value, to restart if we reach the $end number 
        $parser = 0; //Count number elements in 2d array
        $result = 0; //Return the result based on rand(1,5)

        //Create a 2d array(), 5x5 to simulate the 1-5 random number selection from rand(1,5)
        for($row = 0; $row < 5; $row++){
            for($col = 0; $col < 5; $col++){
                $vars[$row][$col] = $start;

                //If the array elements left <= selected range left
                if((25-$parser) <= ($end-$start)){
                    $vars[$row][$col] = 0;
                }else{
                    if($start == $end){
                        $start = $restart;
                    }else{
                        $start++;
                    }
                }       
                $parser++;

            }//END OF FOR COL LOOP
        }//END OF FOR ROW LOOP


        while($result == 0){
            $i = getRandom(); //Choose 1-5
            $j = getRandom(); //Choose 1-5
            $result = $vars[$i-1][$j-1]; //Get number from 2d array, based on rand(1,5)
        }

        echo $result;
    }
mallix
  • 1,399
  • 1
  • 21
  • 44
-2
function getMoreRandom()
{
    $value = 0;
    for($i=1;$i<=5;$i++) $value += getRandom();
    return ($value % 7) + 1;
}
  • First, call getRandom 5 times, to get a range of 5 to 25. This has exactly 21 values - a multiple of 7.
  • Then, find the modulus of 7. This produces a numnber between 0 and 6, and each has a 3 in 21, or 1 in 7, chance of appearing.
  • Then, add one for the correct range.
Gareth Cornish
  • 4,357
  • 1
  • 19
  • 22