I'm building a betting pool system and I have to split the jackpot between all participants given the number of hits (accurate predictions of a certain sport game) they achieved, where more hits means a bigger prize.
For example, if we want to distribute a 1000 coins jackpot for this betting pool, we could use this distribution:
Is there any algorithm to calculate the prize given to each winner given this conditions?
Without knowing how you want to split the prize, one option is to calculate the total number of hits by all users, and divide the jackpot by that number to find the prize awarded to each hit.
You can then just go through and give each user a prize that is this number multiplied by the number of hits.
You can simply define how big the share for which number of hits is
Hits, winWeight, numberOfWinners
5, 24, n(5)
4, 12, n(4)
3, 4, n(3)
2, 2, n(2)
1, 1, n(1)
than you multiply these values with number of winners and get:
total=24*n(5)+12*n(4)+4*n(3)+2*n(2)+1*n(1)
Now you calculate how many coins:
jackpot/total * 24 = pricePerWinner for 5 hits
jackpot/total * 12 = pricePerWinner for 4 hits
jackpot/total * 4 = pricePerWinner for 3 hits
jackpot/total * 2 = pricePerWinner for 2 hits
jackpot/total * 1 = pricePerWinner for 1 hit
Calculating the amount of total hits.
5*6 = 30
4*40 = 160
3*80 = 240
2*20 = 40
1*15 = 15
0*2 = 0
If you add them all up together it would total up to
30+160+240+40+15+0=485
Since there are 1000 coins for the jackpot.
1000/485 ~= 2
This means that for each hit, it would grant 2 coins.
Eg. 5 hits would mean 10 coins per winner
Related
Let's say I have three types of coins -- a penny (0.01), a nickel (0.05), and a dime (0.10) and I want to find the number of ways to make change of a certain amount. For example to change 27 cents:
change(amount=27, coins=[1,5,10])
One of the more common ways to approach this problem is recursively/dynamically: to find the number of ways to make that change without a particular coin, and then deduct that coin amount and find the ways to do it with that coin.
But, I'm wondering if there is a way to do it using a cached value and mod operator. For example:
10 cents can be changed 4 ways:
10 pennies
1 dime
2 nickels
1 nickel, 5 pennies
5 cents can be changed 2 ways:
1 nickel
5 pennies
1-4 cents can be changed 1 way:
1-4 pennies
For example, this is wrong, but my idea was along the lines of:
def change(amount, coins=[1,5,10]):
cache = {10: 4, 5: 2, 1: 1}
for coin in sorted(coins, reverse=True):
# yes this will give zerodivision
# and a penny shouldn't be multiplied
# but this is just to demonstrate the basic idea
ways = (amount % coin) * cache[coin]
amount = amount % ways
return ways
If so, how would that algorithm work? Any language (or pseudo-language) is fine.
Precomputing the number of change possibilities for 10 cents and 5 cents cannot be applied to bigger values in a straight forward way, but for special cases like the given example of pennies, nickels and dimes a formula for the number of change possibilities can be derived when looking into more detail how the different ways of change for 5 and 10 cents can be combined.
Lets first look at multiples of 10. Having e.g. n=20 cents, the first 10 cents can be changed in 4 ways, so can the second group of 10 cents. That would make 4x4 = 16 ways of change. But not all combinations are different: a dime for the first 10 cents and 10 pennies for the other 10 cents is the same as having 10 pennies for the first 10 cents and a dime for the second 10 cents. So we have to count the possibilities in an ordered way: that would give (n/10+3) choose 3 possibilities. But still not all possibilities in this counting are different: choosing a nickel and 5 pennies for the first and the second group of 10 cents gives the same change as choosing two nickels for the first group and 10 cents for the second group. Thinking about this a little more one finds out that the possibility of 1 nickel and 5 pennies should be chosen only once. So we get (n/10+2) choose 2 ways of change without the nickel/pennies split (i.e. the total number of nickels will be even) and ((n-10)/10+2) choose 2 ways of change with one nickel/pennies split (i.e. the total number of nickels will be odd).
For an arbitrary number n of cents let [n/10] denote the value n/10 rounded down, i.e. the maximal number of dimes that can be used in the change. The cents exceeding the largest multiple of 10 in n can only be changed in maximally two ways: either they are all pennies or - if at least 5 cents remain - one nickel and pennies for the rest. To avoid counting the same way of change several times one can forbid to use any more pennies (for the groups of 10 cents) if there is a nickel in the change of the 'excess'-cents, so only dimes and and nickels for the groups of 10 cents, giving [n/10]+1 ways.
Alltogether one arrives at the following formula for N, the total number of ways for changing n cents:
N1 = ([n/10]+2) choose 2 + ([n/10]+1) choose 2 = ([n/10]+1)^2
[n/10]+1, if n mod 10 >= 5
N2 = {
0, otherwise
N = N1 + N2
Or as Python code:
def change_1_5_10_count(n):
n_10 = n // 10
N1 = (n_10+1)**2
N2 = (n_10+1) if n % 10 >= 5 else 0
return N1 + N2
btw, the computation can be further simplified: N = [([n/5]+2)^2/4], or in Python notation: (n // 5 + 2)**2 // 4.
Almost certainly not for the general case. That's why recursive and bottom-up dynamic programs are used. The modulus operator would provide us with a remainder when dividing the amount by the coin denomination -- meaning we would be using the maximum count of that coin that we can -- but for our solution, we need to count ways of making change when different counts of each coin denomination are used.
Identical intermediate amounts can be reached by using different combinations of coins, and that is what the classic method uses a cache for. O(amount * num_coins):
# Adapted from https://algorithmist.com/wiki/Coin_change#Dynamic_Programming
def coin_change_bottom_up(amount, coins):
cache = [[None] * len(coins) for _ in range(amount + 1)]
for m in range(amount+1):
for i in range(len(coins)):
# There is one way to return
# zero change with the ith coin.
if m == 0:
cache[m][i] = 1
# Base case: the first
# coin (which would be last
# in a top-down recursion).
elif i == 0:
# If this first/last coin
# divides m, there's one
# way to make change;
if m % coins[i] == 0:
cache[m][i] = 1
# otherwise, no way to make change.
else:
cache[m][i] = 0
else:
# Add the number of ways to
# make change for this amount
# without this particular coin.
cache[m][i] = cache[m][i - 1]
# If this coin's denomintion is less
# than or equal to the amount we're
# making change for, add the number
# of ways we can make change for the
# amount reduced by the coin's denomination
# (thus using the coin), again considering
# this and previously seen coins.
if coins[i] <= m:
cache[m][i] += cache[m - coins[i]][i]
return cache[amount][len(coins)-1]
With Python you can leverage the #cache decorator (or #lru_cache) and automatically make a recursive solution into a cached one. For example:
from functools import cache
#cache
def change(amount, coins=(1, 5, 10)):
if coins==(): return amount==0
C = coins[-1]
return sum([change(amount - C*x, coins[:-1]) for x in range(1+(amount//C))])
print(change(27, (1, 5, 10))) # 12
print(change(27, (1, 5))) # 6
print(change(17, (1, 5))) # 4
print(change(7, (1, 5))) # 2
# ch(27, (1, 5, 10)) == ch(27, (1, 5)) + ch(17, (1, 5)) + ch(7, (1, 5))
This will invoke the recursion only for those values of the parameters which the result hasn't been already computed and stored. With #lru_cache, you can even specify the maximum number of elements you allow in the cache.
This will be one of the DP approach for this problem:
def coin_ways(coins, amount):
dp = [[] for _ in range(amount+1)]
dp[0].append([]) # or table[0] = [[]], if prefer
for coin in coins:
for x in range(coin, amount+1):
dp[x].extend(ans + [coin] for ans in dp[x-coin])
#print(dp)
return len(dp[amount])
if __name__ == '__main__':
coins = [1, 5, 10] # 2, 5, 10, 25]
print(coin_ways(coins, 27)) # 12
I'm in need of some kind of algorithm I can't figure out on my own sadly.
My biggest problem is that I have no good way to describe the problem... :/
I will try like this:
Imagine you have a racing game where everyone can try to be the fastest on a track or map. Every Map is worth 100 Points in total. If someone finished a map in some amount of time he gets a record in a database. If the player is the first and only player to finish this map he earns all the 100 points of this map.
Now, that's easy ;) but...
Now another player finishes the map. Let's imagine the first player finishes in 50 Seconds and the 2nd player finishes in 55 seconds, so a bit slower. I now need a calculation depending on both records in the database. Each of both players now earn a part of the 100 points. The faster player a bit more then the slower player. Let's say they finished the exact same time they both would get 50 points from 100, but as the first one is slightly faster, he now earns something around 53 of the points and the slower player just 47.
I started to calculate this like this:
Sum of both records is 105 seconds, the faster player took 50/105 in percent of this, so he earns 100-(50/105*100) points and the slower player 100-(55/105*100) points. The key to this is, that all points distributed among the players always equals to 100 in total. This works for 2 players, but it breaks at 3 and more.
For example:
Player 1 : 20 seconds
Player 2 : 20 seconds
Player 3 : 25 seconds
Calculation would be:
Player 1: 100-(20/65*100) = 69 points
Player 2: 100-(20/65*100) = 69 points
Player 3: 100-(25/65*100) = 61 points
This would no longer add up to 100 points in total.
Fair would be something around values of:
Player 1 & 2 (same time) = 35 points
Player 3 = 30 points
My problem is i can't figure out a algorithm which solves this.
And I need the same algorithm for any amount of players. Can someone help with an idea? I don't need a complete finished algorithm, maybe just an idea at which step i used the wrong idea, maybe the sum of all times is already a bad start.
Thx in advance :)
We can give each player points proportional to the reciprocal of their time.
One player with t seconds gets 100 × (1/t) / (1/t) = 100 points.
Of the two players, the one with 50 seconds gets 100 × (1/50) / (1/50 + 1/55) ≈ 52.4, and the one with 55 gets 100 × (1/55) / (1/50 + 1/55) ≈ 47.6.
Of the three players, the ones with 20 seconds get 100 × (1/20) / (1/20 + 1/20 + 1/25) ≈ 35.7, and the one with 25 seconds gets 100 × (1/25) / (1/20 + 1/20 + 1/25) ≈ 28.6.
Simple observation: Let the sum of times for all players be S. A person with lower time t would have a higher value of S-t. So you can reward points proportional to S-t for each player.
Formula:
Let the scores for N players be a,b,c...,m,n. Total sum S = a+b+c...+m+n. Then score for a given player would be
score = [S-(player's score)]/[(N-1)*S] * 100
You can easily see that using this formula, the sum of scores of all players will be always be 100.
Example 1:
S = 50 + 55 = 105, N-1 = 2-1 = 1
Player 1 : 50 seconds => score = ((105-50)/[1*105])*100 = 52.38
Player 2 : 55 seconds => score = ((105-55)/[1*105])*100 = 47.62
Similarly, for your second example,
S = 20 + 20 + 25 = 65
N - 1 = 3 - 1 = 2
For Player 1, (S-t) = 65-20 = 45
Player 1's score => (45/(2*65))*100 = 34.6
Player 2 => same as Player 1
For Player 3, (S-t) = 65-25 = 40
Player 3's score => (40/(2*65))*100 = 30.8
This method avoids any division in the intermediate states, so there will be no floating point issues for the calculations.
This video covers an implementation of the min coins to make change.
https://en.wikipedia.org/wiki/Change-making_problem
The place I'm not clear on is where the interviewer goes into the details of optimization, starting from here.
https://youtu.be/HWW-jA6YjHk?t=1875
He suggests that to make the min number of coins, using denominations [25, 10, 1], we only need to use the algorithm to make change for numbers above 50 cents, after which we can safely just use 25 cents. So if the number was $100.10, we can use 25 cents till we hit 50 cents at which time we need to use the algorithm to compute the precise value.
This makes sense for the list of denominations give [25, 10, 1]. To get the breakpoint figure he suggests using LCM of the denominations which is 50 in this case.
For example
32 - 25 * 1 + 1 * 7 = 8 coins. But with 10 cents we can do
32 - 10 * 3 + 1 * 2 = 5 coins.
So we cannot just assume 25 cents is going to be included in the minimum number of coins calculation.
Here is my question --
Suppose we have denominations [25, 10, 5, 1], the lcm is still 50. But there is no min solution for any number over 25 cents has doesn't include the 25.
eg -
32 - 25 * 1 + 5 * 1 + 1 * 2 = 4 coins.
32 - 10 * 3 + 1 * 2 = 5 coins
So shouldn't the breakpoint be 25 cents in this case? Instead of the lcm?
Thanks for answering.
The LCM of the values provides a minimum upper bound on the "break point", that point at which we cannot blithely assume that the highest-denomination coin is part of the solution. A little number theory will prove that the LCM is a boundary.
50 is the LCM of {25, 10}. For any amount >= 50, any combination including at least 5*10 can replace that element by 2*25, reducing the coin count. This argument applies to all other coins and combinations thereof. This simple demonstration does not universally apply below the LCM; there will be amounts that serve as counterexamples.
To keep the overall algorithm easy to understand and maintain, we use only the two phases: largest coin above that breakpoint, and full DP solution below -- where, for most applications, even a brute-force solution is generally efficient enough for practical purposes.
They didn't say we can't use 25 when the input is lower than the break point. They suggested that a good optimisation can be to use the highest denomination until we reduce the number to the break point (because that is guaranteed to be the least number of coins needed for that portion) and then switch to the more resource-intensive algorithm to count the rest of the needed coins.
Let's assume I have 3 different baskets with a fixed capacity
And n-products which provide different value for each basket -- you can only pick whole products
Each product should be limited to a max amount (i.e. you can maximal pick product A 5 times)
Every product adds at least 0 or more value to all baskets and come in all kinds of variations
Now I want a list with all possible combinations of products fitting in the baskets ordered by accuracy (like basket 1 is 5% more full would be 5% less accurate)
Edit: Example
Basket A capacity 100
Basket B capacity 80
Basket C capacity 30
fake products
Product 1 (A: 5, B: 10, C: 1)
Product 2 (A: 20 B: 0, C: 0)
There might be hundreds more products
Best fit with max 5 each would be
5 times Product 1
4 times Product 2
Result
A: 105
B: 50
C: 5
Accuracy: (qty_used / max_qty) * 100 = (160 / 210) * 100 = 76.190%
Next would be another combination with less accuracy
Any pointing in the right direction is highly appreciated Thanks
Edit:
instead of above method, accuracy should be as error and the list should be in ascending order of error.
Error(Basket x) = (|max_qty(x) - qty_used(x)| / max_qty(x)) * 100
and the overall error should be the weighted average of the errors of all baskets.
Total Error = [Σ (Error(x) * max_qty(x))] / [Σ (max_qty(x))]
I have already read What is an "external node" of a "magic" 3-gon ring? and I have solved problems up until 90 but this n-gon thing totally baffles me as I don't understand the question at all.
So I take this ring and I understand that the external circles are 4, 5, 6 as they are outside the inner circle. Now he says there are eight solutions. And the eight solutions are without much explanation listed below. Let me take
9 4,2,3; 5,3,1; 6,1,2
9 4,3,2; 6,2,1; 5,1,3
So how do we arrive at the 2 solutions? I understand 4, 3, 2, is in straight line and 6,2,1 is in straight line and 5, 1, 3 are in a straight line and they are in clockwise so the second solution makes sense.
Questions
Why does the first solution 4,2,3; 5,3,1; 6,1,2 go anti clock wise? Should it not be 423 612 and then 531?
How do we arrive at 8 solutions. Is it just randomly picking three numbers? What exactly does it mean to solve a "N-gon"?
The first doesn't go anti-clockwise. It's what you get from the configuration
4
\
2
/ \
1---3---5
/
6
when you go clockwise, starting with the smallest number in the outer ring.
How do we arrive at 8 solutions. Is it just randomly picking three numbers? What exactly does it mean to solve a "N-gon"?
For an N-gon, you have an inner N-gon, and for each side of the N-gon one spike, like
X
|
X---X---X
| |
X---X---X
|
X
so that the spike together with the side of the inner N-gon connects a group of three places. A "solution" of the N-gon is a configuration where you placed the numbers from 1 to 2*N so that each of the N groups sums to the same value.
The places at the end of the spikes appear in only one group each, the places on the vertices of the inner N-gon in two. So the sum of the sums of all groups is
N
∑ k + ∑{ numbers on vertices }
k=1
The sum of the numbers on the vertices of the inner N-gon is at least 1 + 2 + ... + N = N*(N+1)/2 and at most (N+1) + (N+2) + ... + 2*N = N² + N*(N+1)/2 = N*(3*N+1)/2.
Hence the sum of the sums of all groups is between
N*(2*N+1) + N*(N+1)/2 = N*(5*N+3)/2
and
N*(2*N+1) + N*(3*N+1)/2 = N*(7*N+3)/2
inclusive, and the sum per group must be between
(5*N+3)/2
and
(7*N+3)/2
again inclusive.
For the triangle - N = 3 - the bounds are (5*3+3)/2 = 9 and (7*3+3)/2 = 12. For a square - N = 4 - the bounds are (5*4+3)/2 = 11.5 and (7*4+3)/2 = 15.5 - since the sum must be an integer, the possible sums are 12, 13, 14, 15.
Going back to the triangle, if the sum of each group is 9, the sum of the sums is 27, and the sum of the numbers on the vertices must be 27 - (1+2+3+4+5+6) = 27 - 21 = 6 = 1+2+3, so the numbers on the vertices are 1, 2 and 3.
For the sum to be 9, the value at the end of the spike for the side connecting 1 and 2 must be 6, for the side connecting 1 and 3, the spike value must be 5, and 4 for the side connecting 2 and 3.
If you start with the smallest value on the spikes - 4 - you know you have to place 2 and 3 on the vertices of the side that spike protrudes from. There are two ways to arrange the two numbers there, leading to the two solutions for sum 9.
If the sum of each group is 10, the sum of the sums is 30, and the sum of the numbers on the vertices must be 9. To represent 9 as the sum of three distinct numbers from 1 to 6, you have the possibilities
1 + 2 + 6
1 + 3 + 5
2 + 3 + 4
For the first group, you have one side connecting 1 and 2, so you'd need a 7 on the end of the spike to make 10 - no solution.
For the third group, the minimal sum of two of the numbers is 5, but 5+6 = 11 > 10, so there's no place for the 6 - no solution.
For the second group, the sums of the sides are
1 + 3 = 4 -- 6 on the spike
1 + 5 = 6 -- 4 on the spike
3 + 5 = 8 -- 2 on the spike
and you have two ways to arrange 3 and 5, so that the group is either 2-3-5 or 2-5-3, the rest follows again.
The solutions for the sums 11 and 12 can be obtained similarly, or by replacing k with 7-k in the solutions for the sums 9 resp. 10.
To solve the problem, you must now find out
what it means to obtain a 16-digit string or a 17-digit string
which sum for the groups gives rise to the largest value when the numbers are concatenated in the prescribed way.
(And use pencil and paper for the fastest solution.)