3v4l.org

run code in 200+ php & hhvm versions
Bugs & Features
<?php # Modelo scenario define("DEFAULT_COU", "default"); define("UTILITY", "minimum_utility"); define("TRAFFIC", "traffic_percent"); define("MODEL_SCENARIO_GROUP_CPM", "cpm_sum"); define("MODEL_SCENARIO_CPM", "cpm"); define("MODEL_SCENARIO_UTILITY", "utility"); define("MODEL_SCENARIO_MEMBERS", "members"); echo 'DATA 1'; echo '<br/>'; $prints = 54700; $data = [ 1 => 26.14, 2 => 5.64, 3 => 5.14, 4 => 7.17, 5 => 8.11, 6 => 7.69, 7 => 7.16, ]; $distribucion = Test::getAdsDistributionV2($data, DEFAULT_COU); $printResult = Test::printDistribution($prints, $distribucion); echo '<br/>'; echo 'Distribución de ' . $prints . ' prints'; print("<pre>" . print_r($printResult, true) . "</pre>"); $spendResult = Test::spendDistribution($data, $printResult); echo 'Spend por anuncio'; print("<pre>" . print_r($spendResult, true) . "</pre>"); $spendTotal1 = Test::spendTotal($spendResult); echo 'SPEND TOTAL DATA 1 = ' . $spendTotal1 . '$'; echo '<br/>'; echo '<br/>'; echo 'DATA 2'; echo '<br/>'; $prints = 54700; $data = [ 1 => 26.14, 2 => 5.64, 3 => 5.14, 4 => 7.17, 5 => 8.11, 6 => 7.69, 7 => 7.16, ]; $distribucion = Test::getAdsDistributionV2($data, 'BR'); $printResult = Test::printDistribution($prints, $distribucion); echo '<br/>'; echo 'Distribución de ' . $prints . ' prints'; print("<pre>" . print_r($printResult, true) . "</pre>"); $spendResult = Test::spendDistribution($data, $printResult); echo 'Spend por anuncio'; print("<pre>" . print_r($spendResult, true) . "</pre>"); $spendTotal2 = Test::spendTotal($spendResult); echo 'SPEND TOTAL 2 = ' . $spendTotal2. '$'; echo '<br/>'; echo '<br/>'; echo 'DIFERENCIA = ' . ($spendTotal2 - $spendTotal1).'$'; echo '<br/>'; echo 'PORCENTAJE DE MEJORA= ' . (($spendTotal2*100/$spendTotal1)-100) . '%'; class Test { public static function spendTotal($spendResult) { $total = 0; foreach ($spendResult as $adId => $spend) { $total += $spend; } return $total; } public static function spendDistribution($data, $printResult) { $result = []; foreach ($printResult as $adId => $dist) { $result[$adId] = $printResult[$adId] * $data[$adId] / 1000; } return $result; } public static function printDistribution($prints, $distribution) { $total = 0; foreach ($distribution as $adId => $dist) { $total += $dist; } $result = []; foreach ($distribution as $adId => $dist) { $result[$adId] = $dist / $total * $prints; } return $result; } public static function getAdsDistributionV2(array $ads, $country) { if ($ads) { $dist = Test::getDist($country); $distGroupsCount = count($dist); arsort($ads); // obtener el CPM mayor de los anuncios a distribuir $firstCpm = reset($ads); // si el primer CPM es válido if ($firstCpm > 0) { // inicialmente tenemos una distribución con todos los anuncios a 0 $adDistribution = array_fill_keys(array_keys($ads), 0); $adsNormalization = array(); for ($i = 1; $i <= $distGroupsCount; $i++) { $dist[$i][MODEL_SCENARIO_GROUP_CPM] = 0; } // para cada anuncio vamos a situarlo en el grupo de CPM que le corresponda foreach ($ads as $adId => $cpm) { // normalizamos entre 0 y 1 la utilidad del anuncio, relativas al máximo CPM $adsNormalization[$adId] = array( MODEL_SCENARIO_CPM => $cpm, MODEL_SCENARIO_UTILITY => $cpm / $firstCpm, ); // IMPORTANTE: si algún anuncio tiene CPM = 0, su utilidad será 0 y tiene que caer obligatoriamente // en el último grupo, a menos que se haya indicado en la uración // una utilidad de 0 para el último grupo, // para cada grupo de CPM de la uración del primero al penúltimo for ($i = 1; $i < $distGroupsCount; $i++) { // si la utilidad del anuncio actual es mayor que la del grupo actual if ($adsNormalization[$adId][MODEL_SCENARIO_UTILITY] >= $dist[$i][UTILITY]) { // ubicamos el anuncio en el grupo de CPM $dist[$i][MODEL_SCENARIO_MEMBERS][$adId] = $cpm; // incrementamos el CPM total de anuncios del grupo con el CPM del anuncio actual $dist[$i][MODEL_SCENARIO_GROUP_CPM] += $cpm; } } // si la utilidad del anuncio actual es menor que la del penúltimo grupo, entonces pertenece al último grupo if ($adsNormalization[$adId][MODEL_SCENARIO_UTILITY] < $dist[$distGroupsCount - 1][UTILITY]) { // ubicamos el anuncio en el último grupo de CPM // no es necesario agregar CPMs pporque se distribuirán uniformemente independientemente del CPM que tengan $dist[$distGroupsCount][MODEL_SCENARIO_MEMBERS][$adId] = 1; } } // calculamos todas las frecuencias de anuncios por grupo, del primero al penúltimo // los anuncios que aparezcan en varios grupos, tendrán más peso pues se llevarán tráfico de cada uno de los grupos for ($i = 1; $i < $distGroupsCount; $i++) { // para cada anuncio dentro del grupo if (isset($dist[$i][MODEL_SCENARIO_MEMBERS])) { foreach ($dist[$i][MODEL_SCENARIO_MEMBERS] as $adId => $cpm) { // aumentamos la frecuencia del anuncio actual según su CPM relativo dentro del grupo actual $adDistribution[$adId] += ($dist[$i][TRAFFIC] * $cpm) / $dist[$i][MODEL_SCENARIO_GROUP_CPM]; } } } // tenemos dentro de $adDistribution todos los anuncios de todos los grupos (menos el último) con sus frecuencias relativas // si hay anuncios en el último grupo if (isset($dist[$distGroupsCount][MODEL_SCENARIO_MEMBERS])) { // todos los anuncios del último grupo tienen la misma frecuencia relativa, distribuyendo el tráfico correspondiente $distribution = $dist[$distGroupsCount][TRAFFIC] / count($dist[$distGroupsCount][MODEL_SCENARIO_MEMBERS]); // actualizamos las frecuencias relativas de los anuncios del último grupo foreach ($dist[$distGroupsCount][MODEL_SCENARIO_MEMBERS] as $adId => $cpm) { $adDistribution[$adId] = $distribution; } } // eliminamos todos los elementos que puedan quedar con frecuencia 0 $adDistribution = Test::array_diff($adDistribution, array(0)); // normalizamos la distribución de cada anuncio ganador tomando como base la menor frecuencia $divide = false; foreach ($adDistribution as $adId => $frequency) { if (intval($frequency) == 0) { $divide = true; break; } } if ($divide) { // obtenemos el valor de la menor frecuencia arsort($adDistribution); $lastProbability = end($adDistribution); foreach ($adDistribution as $adId => &$frequency) { $frequency = intval($frequency / $lastProbability); } } else { foreach ($adDistribution as $adId => &$frequency) { $frequency = intval($frequency); } } } else { // @codeCoverageIgnoreStart // todos los anuncios se distribuyen uniformemente $adDistribution = array_fill_keys(array_keys($ads), 1); // @codeCoverageIgnoreEnd } } else { // @codeCoverageIgnoreStart $adDistribution = array(); // @codeCoverageIgnoreEnd } return $adDistribution; } public static function array_diff(array $b, array $a) { $at = array(); foreach ($a as $i) { $at[(string)$i] = 1; } $d = array(); foreach ($b as $k => $i) { if (!isset($at[(string)$i])) { $d[$k] = $i; } } return $d; } public static function getDist($country) { $distributions = array( "BR" => array( 1 => array( UTILITY => 0.9, TRAFFIC => 85, ), 2 => array( UTILITY => 0.55, TRAFFIC => 10, ), 3 => array( UTILITY => 0.45, TRAFFIC => 4, ), 4 => array( UTILITY => 0, TRAFFIC => 1, ), ), DEFAULT_COU => array( 1 => array( UTILITY => 0.70, TRAFFIC => 70, ), 2 => array( UTILITY => 0.55, TRAFFIC => 20, ), 3 => array( UTILITY => 0.45, TRAFFIC => 8, ), 4 => array( UTILITY => 0, TRAFFIC => 2, ), ), ); return $distributions[$country]; } } ?>
based on NrLr9
Output for 7.0.0 - 7.2.0
DATA 1<br/><br/>Distribución de 54700 prints<pre>Array ( [1] => 53606 [5] => 182.33333333333 [6] => 182.33333333333 [4] => 182.33333333333 [7] => 182.33333333333 [2] => 182.33333333333 [3] => 182.33333333333 ) </pre>Spend por anuncio<pre>Array ( [1] => 1401.26084 [5] => 1.4787233333333 [6] => 1.4021433333333 [4] => 1.30733 [7] => 1.3055066666667 [2] => 1.02836 [3] => 0.93719333333333 ) </pre>SPEND TOTAL DATA 1 = 1408.7200966667$<br/><br/>DATA 2<br/><br/>Distribución de 54700 prints<pre>Array ( [1] => 54153 [5] => 91.166666666667 [6] => 91.166666666667 [4] => 91.166666666667 [7] => 91.166666666667 [2] => 91.166666666667 [3] => 91.166666666667 ) </pre>Spend por anuncio<pre>Array ( [1] => 1415.55942 [5] => 0.73936166666667 [6] => 0.70107166666667 [4] => 0.653665 [7] => 0.65275333333333 [2] => 0.51418 [3] => 0.46859666666667 ) </pre>SPEND TOTAL 2 = 1419.2890483333$<br/><br/>DIFERENCIA = 10.568951666666$<br/>PORCENTAJE DE MEJORA= 0.75025206864545%
Output for 5.4.0 - 5.6.28
DATA 1<br/><br/>Distribución de 54700 prints<pre>Array ( [1] => 53606 [2] => 182.33333333333 [3] => 182.33333333333 [7] => 182.33333333333 [4] => 182.33333333333 [5] => 182.33333333333 [6] => 182.33333333333 ) </pre>Spend por anuncio<pre>Array ( [1] => 1401.26084 [2] => 1.02836 [3] => 0.93719333333333 [7] => 1.3055066666667 [4] => 1.30733 [5] => 1.4787233333333 [6] => 1.4021433333333 ) </pre>SPEND TOTAL DATA 1 = 1408.7200966667$<br/><br/>DATA 2<br/><br/>Distribución de 54700 prints<pre>Array ( [1] => 54153 [2] => 91.166666666667 [3] => 91.166666666667 [7] => 91.166666666667 [4] => 91.166666666667 [5] => 91.166666666667 [6] => 91.166666666667 ) </pre>Spend por anuncio<pre>Array ( [1] => 1415.55942 [2] => 0.51418 [3] => 0.46859666666667 [7] => 0.65275333333333 [4] => 0.653665 [5] => 0.73936166666667 [6] => 0.70107166666667 ) </pre>SPEND TOTAL 2 = 1419.2890483333$<br/><br/>DIFERENCIA = 10.568951666666$<br/>PORCENTAJE DE MEJORA= 0.75025206864545%