Recently, I was confronted with the task of writing a “rotator” of some objects, the priority of which I must display myself. The point is simple: more priority - more object hits.
However, at the design stage of the algorithm, several unpleasant features were found.
Well, first of all, I wanted to get by with minimal changes in the database. I really did not want to make a separate table in mysql to count the number of impressions. But resigned to this fact, he continued to design. The first algorithm that I built was all dull but on paper a couple of rotations went through and worked quite well.
Its essence was that in the rotation table we write not only the number of real impressions, but also a certain number using the formula (hereinafter, the lowering formula)
20 - 2iwhere i is the rotation priority. The meaning of this formula is that when I show an object, I will choose from the base an instance with the minimum reduction formula and add one more unit to the current sum of the previous reduction formulas. Thus, it turns out that an object with a large rotation coefficient (the one that I want to show more) will be encountered more often, because a smaller number will be added to the lowering formula than for objects with a lower coefficient.
The next problem I sorted out is problem “20”. That is, on this algorithm it would be possible to set the rotation coefficient only from 0 to 9 (if we take only numbers from the series of natural numbers). The reducing formula has been transformed now depending on the number of objects:
2n - iwhere n is the number of objects in the database suitable for rotation. But now some restrictions have been imposed: the rotation rate cannot exceed the total number of rotation objects. That is, when
')
2n - i
0 <= i <= n
Looking ahead, I will say that this actually kills one and a half hare. And it is killed by the fact that one of the problems is solved when adding a new object. Now, when adding an object, it remains only to make small manipulations:
1 - decide whether to increase all current object coefficients by 1;
2- write an initiative lowering formula into the rotation record, or take the sum from any record already. After a few iterations, the shows will go as they should.
In general, what this form is good for is that by using the coefficients in a decreasing formula, you can rank the power of the effect that gives the rotation coefficient (that is, how much more factor 2 will affect the results than 1 or 0)
But as I said, I was not satisfied with the way where I would have to create a separate table in the database or add garbage fields. The final, working solution came to me when I thought about the following: “The coefficient should show how much larger the object should be shown in the sample. If there are coefficients 2 3 1 1, the objects from 7 times should be shown approximately 2 3 1 1 times, respectively. ”And here another thought came to me, bydloderderskaya, but satisfying my main requirement. All I needed was to add a rotation coefficient to the object. Then it’s all a matter of sampling: when sampling, I select all the rotation objects and fill the array with duplicates according to the rotation coefficient. That is, having objects and coefficients:
1 2 3 4
2 3 1 1
The rotation array will be:
o1 o1 o2 o2 o2 o3 o4
Now it remains only to mix it, and select a random element. According to probability theory, everything is correct: the greater the rotation coefficient, the greater the chances of choosing this object. At first glance, it seems that ranking the power of the influence of the coefficient on the rotation does not work, but no one bothers to make a factor for the coefficient, or to build it in a square or cube (if there are a lot of objects). Note that the new object will stand in such a rotational scheme without any crutches.