Dynamic Programming Problem - Maximize Profit by Selling Stocks - algorithm

I am looking at this code challenge:
You are selling stocks over n days and you have x number of stocks.
x = y1 + y2 + ... + yn denoting the number of stocks you sell per day over n days.
There is a list of default prices for each day p[1..n] and a list of selling deduction f[0..x].
Selling deduction depends on how many stocks you sell at a time hence 0 to x.
Actual price per day depends on how many stocks you sell.
For instance, p[1] is 500 and f[120] is 60. If you have 200 stocks and you sell 120 on day 1.
Profit = 120 * (500 - 60) = 50400
The deduction carries on into subsequent days, so if you sell the remaining stocks on day 2 with p[2] = 300 and f[80] = 40.
Profit = 80 * (300 - 40 - 60) = 16000
I'm trying to maximize total profit by deciding how many stocks to sell on each day.
I'm not very good at DP problems and have only practiced the traditional problems. I'm getting kind of stuck on this one. I think the approach might use a 3D array with x, n, and p being number of stocks, number of days, and price on that day after the deductions from previous days and the day of if applicable.
I'm trying to figure out the recurrence first for P(x,i,p) denoting maximum profit by selling x shares by day i with p being the price of stocks on day i, but I'm getting stuck as well trying to figure out patterns by working with small examples.
How can I approach this?

One simple recursive that could solve this problem in O(x * n) is like bellow (Where x is the total amount of stocks and n is the total number of days) :
p = [100, 200, 90, 190]
f = [1, 3, 4, 5, 6, 3, 5]
def max_profit(stocks, day):
if day == 1:
return stocks * (p[day - 1] - f[stocks - 1]), [stocks]
max = 0
history = []
for i in range(0, stocks + 1):
prev_profit, prev_history = max_profit(stocks - i, day - 1)
profit = prev_profit + i * (p[day - 1] * f[stocks - 1])
if profit > max:
max = profit
history = prev_history
history.append(i)
return max, history
print(max_profit(7, 4))
In this algorithm I've considered all the ways that is possible to sell stock, I mean 0 share , 1 share, 2 share , .... x shares, and then called max_profit for previouse day recursively.

Related

Algorithm to distribute a jackpot between winners

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

Algorithm: Fill different baskets

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))]

how to find maximum profit while selling some garbage item

I have one problem statement for which i need write an algo. can somebody help me?
Problem is :
i have different length of iron rod let say {26, 103, 59}, i want to sell the same length of iron rod so that i can earn maximum profit. Also i have to cutting charge lets say 10 Rs/unit.
Case 1, if cutting charge is Rs 100 and sell length of 51 feet with cost 100 per unit.
then 103/ 51 = 2 length ((51 * 100 * 2) - ((1 * 100) + 200 ) = 9900
59 / 51 = 1 length ((51 * 100 * 1) - ((8 * 100) + 1* 100) = 4200
26/52 = 0 length((0 * 100)) - (26 * 100 ) = -2600
now total profit is = 11500
But if cutting charge is vary then this calculation like failed, can some one tell how can develop algo to find the maximum profit.

Find the nearest nice number

Given a base currency of GBP £, and a table of other currencies accepted in a shop:
Currency Symbol Subunits LastToGBPRate
------------------------------------------------------
US Dollars $ 100 0.592662000
Euros € 100 0.810237000
Japanese Yen ¥ 1 0.005834610
Bitcoin ฿ 100000000 301.200000000
We have a working method that converts a given amount in GBP Pence (AKA cents) into Currency X cents. Given a price of 999 (£9.99), for the above currencies it would return:
Currency Symbol
---------------------
US Dollars 1686
Euros 1233
Japanese Yen 1755
Bitcoin 3482570
This is all working absolutely fine. We then have a Format Currency method which converts them all into nice looking numbers:
Currency Formatted
---------------------
US Dollars $16.86
Euros €12.33
Japanese Yen ¥1755
Bitcoin ฿0.03482570
Now the problem we want to solve, is to round these amounts to the nearest meaningful pretty number in a general purpose algorithm given the information above.
This serves two important benefits:
Prices for most currencies should appear static for visitors over short-medium term time frames
Presents the visitor with a culturally meaningul price point which encourages sales
A meaningful number is one where the smallest unit displayed isn't smaller than the value of say £0.10, and a pretty number is one which ends in 49 or 99. Example outputs:
Currency Formatted Meaninful and Pretty
-----------------------------------------------------
US Dollars $16.86 $16.99
Euros €12.33 €12.49
Japanese Yen ¥1755 ¥1749
Bitcoin ฿0.03482570 ฿0.0349
I know it is possible to do this with a single algorithm with all the information given, but I'm struggling to work out even where to start. Can anyone show me how to achieve this, or give pointers?
Please note, storing a general formatting rule for each currency is not adequate because assume for example the price of Bitcoin 10x's, the formatting rule will need updating. I'm looking for a solution that doesn't need any manual maintainance/checking.
For a given decimal value X, you want to find the smallest integer Y such that YA + B as close as possible to X, for some given A and B. E.g. in the case of dollar, you have A = .5 and B = .49.
In general, for your problem, A and B can be computed via the formula:
V = value of £0.10 in target currency
K = smallest power of ten (10^k) such that 9*10^k >= V
and k <= -2 (this condition I added based on your examples, but contrary
to your definition)
= 10^min(-2, ceil(log10(V / 9)))
A = 50 * K
B = 49 * K
Note that without the extra condition, since 0.09 dollars is less than 0.10 pounds, we would get 14.9 as the result for 16.86 dollars.
With some transformation we get
Y ~ (X - B) / A
And since Y is integer, we have
Y = round((X - B) / A)
The result is then YA + B.
Convert £0.10 to the current currency to determine the smallest displayable digit (SDD)
(bounded by the number of available digits in that currency).
Now we basically have 3 choices of numbers:
... (3rdSDD-1) 9 9 (if 3rdSDD is 0, it will obviously carry from 4thSDD and so on, as subtraction normally works)
We'll pick this when 10*2ndSDD + 1stSDD < 24
... 3rdSDD 4 9
We'll pick this when 24 <= 10*2ndSDD + 1stSDD < 74
... 3rdSDD 9 9
We'll pick this when 74 < 10*2ndSDD + 1stSDD
It should be trivial to figure it out from here.
Some multiplication and modulus to get you 2ndSDD and 1stSDD.
Basic subtraction to get you ... (3rdSDD-1).
A few if-statements to pick one of the above cases.
Example:
For $16.86, our 3 choices are $15.99, $16.49 and $16.99.
We pick $16.99 since 74 < 86.
For €12.33, our 3 choices are €11.99, €12.49 and €12.99.
We pick €12.49 since 24 <= 33 < 74.
For ¥1755, our 3 choices are ¥1699, ¥1749 and ¥1799.
We pick ¥1749 since 24 <= 55 < 74.
For ฿0.03482570, our 3 choices are ฿0.0299, ฿0.0349 and ฿0.0399.
We pick ฿0.0349 since 24 <= 48 < 74.
And, just to show the carry:
For $100000.23, our 3 choices are $99999.99, $100000.49 and $100000.99.
We pick $99999.99 since 23 < 24.
Here's an ugly answer:
def retail_round(number):
"""takes a decimal.Decimal and retail rounds it"""
ending_digits = str(number)[-2:]
if not ending_digits in ("49","99"):
rounding_adjust = (99 - int(ending_digits)) % 50
if rounding_adjust <= 25:
number = str(number)[:-2]+str(int(ending_digits)+int(rounding_adjust))
else:
if str(number)[-3] == '.':
number = str(int(number) - .01)
else:
number = str(int(str(number)[:-2]+"00")-1)
return decimal.Decimal(number)
>>> import decimal
>>> retail_round(decimal.Decimal("15.50"))
Decimal('14.99')
>>> retail_round(decimal.Decimal("15.51"))
Decimal('14.99')
>>> retail_round(decimal.Decimal("15.75"))
Decimal('15.99')
>>> retail_round(decimal.Decimal("1575"))
Decimal('1599')
>>> retail_round(decimal.Decimal("1550"))
Decimal('1499')
EDIT: this is a bit better solution, using decimal.Decimal
Currency = collections.namedtuple("Currency",["name","symbol",
"subunits"])
def retail_round(currency, amount):
"""returns a decimal.Decimal amount of the currency, rounded to
49 or 99."""
adjusted = ( amount / currency.subunits ) % 100 # last two digits
print(adjusted)
if adjusted < 24:
amount -= (adjusted + 1) * currency.subunits # down to 99
elif 24 <= adjusted < 74:
amount -= (adjusted - 49) * currency.subunits # to 49
else:
amount -= (adjusted - 99) * currency.subunits # up to 99
return amount
Calculate the maximum length of the price, assume its something like 0.00001. (You can do that by changing £0.10 to the currency, then taking the 10 base log of it, getting its ceil and that power of 10).
Eg: £0.10 = 17.1421309¥
log(17.1421309) = 1.234
ceil(1.234) = 2
10^2 = 100
so
¥174055 will be ¥174900
Adjust the number for the digit, add 1, round to 50, subtract 1:
174055 -> (round((174055/100+1)/50)*50-1)*100 = 174900
Plain and simple.

Calculating bid price from total cost

I have to following problem to solve. I have to calculate the bidding price from a total price. For example, a client wants to pay 2000$ as a total price, but from this price, there are added costs:
-usage price which is 10% from the bidding price with a minimum of 10$ and a maximum of 50$
-seller price: 2% from bidding price
-added price: 5$ for a bid between 1 and 500
10$ for a bid between 501 and 1000
15$ for a bid between 1001 and 3000
20$ for a bid over 3000$
-storing cost: 100$
from all this, I have to calculate the bidding price for a total of 2000$, for example. I kind of have no clue of how this can be done. Can anyone give me some hints or pieces of answer of what the algorithm should be?
EDIT: ok I got how to calculate the algebra, now where i'm stuck is how to write the algorithm in code or pseudo-code. Anyone got a hint?
You can express all those costs as a function of the bid price. Generate a giant equation that is the sum of all those functions and solve for a particular final value, e.g.:
usage cost(bid) = PIN(bid*0.10, 10, 50)
seller cost(bid) = bid*.02
added cost(bid) = PIN(ceiling(bid/500)*5, 5, 10) + PIN(ceiling((bid - 1000)/2000)*5, 0, 10)
storing cost(bid) = 100
So the final cost is something like:
final cost(bid) = PIN(bid*.1, 10, 50) + pin(ceiling(bid/500)*5, 5, 20) + PIN(ceiling((bid - 1000)/2000)*10, 0, 20) + bid*.02 + 100 + bid
Solve for a particular value and you're done.
For example, if you want the total cost to be $2000:
2000 = PIN(bid*.1, 10, 50) + pin(ceiling(bid/500)*5, 5, 10) + PIN(ceiling((bid - 1000)/2000)*5, 0, 10) + bid*.02 + 100 + bid.
Bid must be at least > 1500 and < 2000, which works out nicely since we can make those PIN sections constant:
2000 = 50 + 10 + 5 + 100 + bid*1.02
1835 = bid*1.02
bid = 1799.0196078431372549019607843137
The PIN expressions are the hardest to factor out, so you might have to guess a few times until you get something that narrows down the range of bids you want to calculate.

Resources