Hydra IO
Hydra IO

Reputation: 1557

Weighted array based on user input

I am attempting to allow a user to create an array of index's which are then added to an array with a percentage associated with it. Here is an example:

EX1

$pages[] = array('index1.php','25');
$pages[] = array('index2.php','25');
$pages[] = array('index3.php','50');

or

EX2

$pages[] = array('index1.php','25');
$pages[] = array('index2.php','75');

or even

EX3

$pages[] = array('index1.php','25');
$pages[] = array('index2.php','25');
$pages[] = array('index3.php','25');
$pages[] = array('index4.php','25');

I would like to then create a file with the following contents:

OUTPUT EX1

index1.php
index2.php
index3.php
index3.php

OUTPUT EX2

index1.php
index2.php
index2.php
index2.php

OUTPUT EX3

index1.php
index2.php
index3.php
index4.php

Would I just take the sum of $page[][1] and divide by the number of items in the array?

Upvotes: 2

Views: 62

Answers (3)

Greenonion
Greenonion

Reputation: 87

Actually i will not agree with answer, let's say you have

$pages[] = array('index1.php','10');
$pages[] = array('index2.php','20');
$pages[] = array('index3.php','40');
$pages[] = array('index4.php','35');

Then your output will be:

index1.php
index2.php
index2.php
index3.php
index3.php
index3.php
index3.php
index4.php
index4.php
index4.php

And this output is wrong. As you see we have index4 three times here.

To compute correct values you should use greatest common divisor. For example:

/*
* function gcd()
* 
* returns greatest common divisor
* between two numbers
* tested against gmp_gcd()
*/
function gcd($a, $b)
{
    if ($a == 0 || $b == 0)
        return abs( max(abs($a), abs($b)) );

    $r = $a % $b;
    return ($r != 0) ?
        gcd($b, $r) :
        abs($b);
}

/*
* function gcd_array()
* 
* gets greatest common divisor among
* an array of numbers
*/
function gcd_array($array, $a = 0)
{
    $b = array_pop($array);
    return ($b === null) ?
        (int)$a :
        gcd_array($array, gcd($a, $b));
}

$array = [10,20,40,35];
$result = gcd_array($array);

for ($i = 0; $i < sizeof($array); $i++)
{
  echo $array[$i] / $result;
  echo "\r\n";
}

In this case output will be:

2 4 8 7

(index1 - 2 times, index2 - 4 times, index 3 - 8 times, index4 - 7 times)

and on my opinion this is correct.

Upvotes: 0

Kevin
Kevin

Reputation: 41885

Just get the minimum number, then just divide it by that, then use str_repeat. (I don't know what's the better way.). Sample Code:

$pages[] = array('index1.php','25');
$pages[] = array('index2.php','25');
$pages[] = array('index3.php','25');
$pages[] = array('index4.php','25');

$min = min(array_map(function($weight){
    return $weight[1];
}, $pages));

foreach($pages as $page) {
    echo str_repeat($page[0] . '<br/>', $page[1] / $min);
}

Upvotes: 2

Rob Cozzens
Rob Cozzens

Reputation: 136

If you don't mind redundancy, just list the file the number of times given by the weight. For example, you would list index1.php (25/25) times (1), and index3.php (50/25) times (2).

Upvotes: 2

Related Questions