Hello, Buffer

Weighted distrobution with non-uniform sets

The problem is as follows A customer will order a set of views in one of two configurations:

Full Frame logo: 1/4 Logo:

    +------------+       +-----+------+
    |            |       | A   | B    |
    |            |       +-----+------+
    |Full Frame  |       | C   | D    |
    +------------+       +-----+------+

So i have a set of customers with properties:

  • Name
  • Limit (Amout of views they purchased)
  • Shown (Amout of views aquired)
  • FullScreen (If it’s a fullscreen or not)

I then try to generate every possible screen and give it a score(Later to be used as weight): I also iterate over every customer to gain a `total_remaining` for use in the `weight`

for customer in customers:
    remaining = customer['limit'] - customer['shown']
    total_remaining += remaining
    if remaining < 0:
        continue
    if customer['fullscreen']:
        possible_fullscreeens.append({
            'name': customer['name'],
            'limit': customer['limit'],
            'shown': customer['shown'],
            'remaining': remaining
        })
    if not customer['fullscreen']:
        possible_quarts.append({
            'name': customer['name'],
            'limit': customer['limit'],
            'shown': customer['shown'],
            'remaining': remaining
        })

Both fullscreen and quarts are now in a temporary dict, i neeede to iterate over twice to get the `total_remaining`

And for then we add all possible screens in `possible_ads` For the fullscreen this is straight forward:

for full in possible_fullscreeens:
    possible_ads.append({
        "name":
        full['name'],
        "score":
        full['remaining'],
        "remaining":
        full['remaining'],
        "weight": (full['remaining'] / total_remaining) * 100.0
    })

For quarts this is a lot more work, and i probably did it wrong in a stupid way. But here we go.

# First i get all the possible combinations for the given set
possible_combinations = get_possible_combinations(len(possible_quarts), 4)
for subset in itertools.combinations(possible_quarts, 4):
    score = 0
    name = ""
    for customer in subset:
        customer_name = customer['name']
        name += customer_name + ','
        score += customer['remaining'] / 4.0

    possible_ads.append({
        "name":
        name,
        "score":
        score,
        "remaining":
        score,
        "weight":
        ((score / total_remaining) * 100.0) / (possible_combinations)
    })

Then we use the weights to do a weighted random selection

(total_remaining, possible_ads) = update_adds()
if (len(possible_ads) <= 1):
    print("All done")
    break
weights = []
for ad in possible_ads:
    weights.append(ad['weight'])

ad = secure_random.choices(possible_ads, weights=weights, k=1)[0]

My assumtion is that it should take about as long for everyone to reach the limit, i have some wierd distrobution in that respect This is the response after 100_000 runs, the lower letters have high numbers because their limits is low, and `A`,`A1` and `A2` are fullscreen

A    %:      24.82
A2   %:      24.908
A3   %:      24.81
B    %:      19.68
C    %:      19.296
D    %:      19.42
F    %:      3.7216
G    %:      36.724000000000004
H    %:      36.832
I    %:      37.532
K    %:      37.104
L    %:      100.02
M    %:      100.05
P    %:      105.0
Q    %:      110.00000000000001

This needs more work