Ad system tips
I create an ad system that shows the ads with the highest price more often.
Here is an example of the table structure I am using, but simplified ...
+----+----------+------------------------+----------------------+-----+
| id | name | image | destination | bid |
+----+----------+------------------------+----------------------+-----+
| 1 | abc, co | htt.../blah | htt...djkd.com/ | 3 |
+----+----------+------------------------+----------------------+-----+
| 2 | facebook | htt.../blah | htt...djkd.com/ | 200 |
+----+----------+------------------------+----------------------+-----+
| 3 | google | htt.../blah | htt...djkd.com/ | 78 |
+----+----------+------------------------+----------------------+-----+
Now, right now I am fetching values from the database and then inserting them into an array and selecting from them at random, similar to the following:
$ads_array = [];
$ads = Ad::where("active", "=", 1)->orderBy("price", "DESC");
if ($ads->count() > 0) {
$current = 0;
foreach ($ads->get() as $ad) {
for ($i = 0; $i <= ($ad->price == 0 ? 1 : $ad->price); $i++) {
$ads_array[$current] = $ad->id;
$current++;
}
}
$random = rand(0,$current-1);
$ad = Ad::where("id", "=", $ads_array[$random])->first();
...
}
So, in essence, this is what it inserts the ad id into an array of 1*$bid
times. This is very inefficient unfortunately (for obvious reasons), but it was the best way I could think of it.
Is there a better way to select a random ad from my database? while giving higher bidders a higher likelihood of showing up?
source to share
It looks like it might do the trick (but all credits go to this guy in the comments )
SELECT ads.*
FROM ads
ORDER BY -log(1.0 - rand()) / ads.bid
LIMIT 1
A script to test this:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;', 'test', 'test');
$times = array();
// repeat a lot to have real values
for ($i = 0; $i < 10000; $i++) {
$stmt = $pdo->query('SELECT ads.* FROM ads ORDER BY -log(1.0 - rand()) / bid LIMIT 1');
$bid = $stmt->fetch()['bid'];
if (isset($times[$bid])) {
$times[$bid] += 1;
} else {
$times[$bid] = 1;
}
}
// echoes the number of times one bid is represented
var_dump($times);
The numbers that come to me from this test are pretty good:
// key is the bid, value is the number of times this bid is represented
array (size=3)
200 => int 7106
78 => int 2772
3 => int 122
Further link to math explanation
Many important univariate distributions can be selected by inversion using simple closed-form expressions. Some of the more useful ones are listed here.
Example 4.1 (Exponential distribution). The standard exponential distribution has a density f (x) = ex on x> 0. If X has this distribution, then E (X) = 1, and we write X ~ Exp (1). Cumulative distribution function F (x) = P (X x) = 1 - ex, and F-1 (u) = -log (1 - u). Therefore, taking X = - log (1 - U) for U ~ U (0, 1) generates standard exponential random variables. Additional call uses X = - log (U).
The exponential distribution with the rate λ> 0 (and the mean value θ = 1 / λ) has PDF λexp (-λx) for 0 x <∞. If X has this distribution, then we write X ~ Exp (1) / λ or equivalently X ~ θExp (1), depending on whether the problem is more naturally formulated in terms of rate λ or mean θ. We can generate X by taking X = - log (1 - U) / λ.
coming from http://statweb.stanford.edu/~owen/mc/Ch-nonunifrng.pdf
source to share