Minimum number of coins for a given sum and denominations - dynamic-programming

Given a set of denominations and the sum required I have to find the minimum number of coins that make that sum and also the number of coins for each denominations
Please help!!

The pseudo-code to determine minimum number of coins needed to make that sum is:
Procedure coinChange(coins, total):
n := coins.length
dp[n][total + 1]
for i from 0 to n
dp[i][0] := 0
end for
for i from 1 to (total + 1)
dp[0][i] := i
end for
for i from 1 to n
for j from 1 to (total + 1)
if coins[i] > j //if the denomination is greater than total
dp[i][j] := dp[i-1][j]
else //if the denomination is less than or equal to total
dp[i][j] := min(dp[i-1][j], dp[i][j-coins[i]])
end if
end for
end for
Return dp[n-1][total]
And to find out the denominations needed:
Procedure printChange(coins, dp, total):
i := coins.length - 1
j := total
min := dp[i][j]
while j is not equal to 0
if dp[i-1][j] is equal to min //if the value came from the top we didn't choose current coin
i := i - 1
else
Print(coins[i])
j := j - coins[i]
end if
end while
If you want to print the number of each denomination, just after printing the coins[i], you need to print the difference of dp[j] and dp[j - coins[i]]. The rest of the code will be same.
The full description of this solution used to be found in SO Docs, but has now been moved here.
Coin Changing Problem
Minimum number of coins to get total
Given coins of different denominations and a total, how many coins do we need to combine to get the total if we use minimum number of coins? Let's say we have coins = {1, 5, 6, 8} and a total = 11, we can get the total using 2 coins which is {5, 6}. This is indeed the minimum number of coins required to get 11. We'll also assume that there are unlimited supply of coins. We're going to use dynamic programming to solve this problem.
We'll use a 2D array dp[n][total + 1] where n is the number of different denominations of coins that we have. For our example, we'll need dp[4][12]. Here dp[i][j] will denote the minimum number of coins needed to get j if we had coins from coins[0] up to coins[i]. For example dp[1][2] will store if we had coins[0] and coins[1], what is the minimum number of coins we can use to make 2. Let's begin:
At first, for the 0th column, can make 0 by not taking any coins at all. So all the values of 0th column will be 0. For dp[0][1], we are asking ourselves if we had only 1 denomination of coin, that is coins[0] = 1, what is the minimum number of coins needed to get 1? The answer is 1. For dp[0][2], if we had only 1, what is the minimum number of coins needed to get 2. The answer is 2. Similarly dp[0][3] = 3, dp[0][4] = 4 and so on. One thing to mention here is that, if we didn't have a coin of denomination 1, there might be some cases where the total can't be achieved using 1 coin only. For simplicity we take 1 in our example. After first iteration our dp array will look like:
+---+---+---+---+---+---+---+---+---+---+---+---+---+
(denom)| | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
+---+---+---+---+---+---+---+---+---+---+---+---+---+
(1) | 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
+---+---+---+---+---+---+---+---+---+---+---+---+---+
(5) | 1 | 0 | | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+
(6) | 2 | 0 | | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+
(8) | 3 | 0 | | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+
Moving on, for dp[1][1], we are asking ourselves if we had coins[0] = 1 and coins[1] = 5, what is the minimum number of coins needed to get 1? Since coins[1] is greater than our current total, it will not affect our calculation. We'll need to exclude coins[5] and get 1 using coins[0] only. This value is stored in dp[0][1]. So we take the value from the top. Our first formula is:
if coins[i] > j
dp[i][j] := dp[i-1][j]
This condition will be true until our total is 5 in dp[1][5], for that case, we can make 5 in two ways:
- We take 5 denominations of coins[0], which is stored on dp[0][5] (from the top).
- We take 1 denomination of coins[1] and (5 - 5) = 0 denominations of coins[0].
We'll choose the minimum of these two. So dp[1][5] = min(dp[0][5], 1 + dp[1][0]) = 1. Why did we mention 0 denominations of coins[0] here will be apparent in our next position.
For dp[1][6], we can make 6 in two ways:
- We take 6 denominations of coins[0], which is stored on the top.
- We can take 1 denomination of 5, we'll need 6 - 5 = 1 to get the total. The minimum number of ways to get 1 using the coins of denomination 1 and 5 is stored in dp[1][1], which can be written as dp[i][j-coins[i]], where i = 1. This is why we wrote the previous value in that fashion.
We'll take the minimum of these two ways. So our second formula will be:
if coins[i] >= j
dp[i][j] := min(dp[i-1][j], dp[i][j-coins[i]])
Using these two formulae we can fill up the whole table. Our final result will be:
+---+---+---+---+---+---+---+---+---+---+---+---+---+
(denom)| | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
+---+---+---+---+---+---+---+---+---+---+---+---+---+
(1) | 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
+---+---+---+---+---+---+---+---+---+---+---+---+---+
(5) | 1 | 0 | 1 | 2 | 3 | 4 | 1 | 2 | 3 | 4 | 5 | 2 | 3 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+
(6) | 2 | 0 | 1 | 2 | 3 | 4 | 1 | 1 | 2 | 3 | 4 | 2 | 2 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+
(8) | 3 | 0 | 1 | 2 | 3 | 4 | 1 | 1 | 2 | 1 | 2 | 2 | 2 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+
Our required result will be stored at dp[3][11]. The procedure will be:
Procedure coinChange(coins, total):
n := coins.length
dp[n][total + 1]
for i from 0 to n
dp[i][0] := 0
end for
for i from 1 to (total + 1)
dp[0][i] := i
end for
for i from 1 to n
for j from 1 to (total + 1)
if coins[i] > j
dp[i][j] := dp[i-1][j]
else
dp[i][j] := min(dp[i-1][j], dp[i][j-coins[i]])
end if
end for
end for
Return dp[n-1][total]
The runtime complexity of this algorithm is: O(n*total) where n is the number of denominations of coins.
To print the coins needed, we need to check:
- if the value came from top, then the current coin is not included.
- if the value came from left, then the current coin is included.
The algorithm would be:
Procedure printChange(coins, dp, total):
i := coins.length - 1
j := total
min := dp[i][j]
while j is not equal to 0
if dp[i-1][j] is equal to min
i := i - 1
else
Print(coins[i])
j := j - coins[i]
end if
end while
For our example, the direction will be:
The values will be 6, 5.

there are 3 typos in the code :
first :
if coins[i] >= j
dp[i][j] := min(dp[i-1][j], dp[i][j-coins[i]])
this should be :
if coins[i] > j <-- HERE
dp[i][j] := min(dp[i-1][j], dp[i][j-coins[i]])
second : also in the same previous code, the second part of the min is missing + 1
so the correct code would be
if coins[i] > j
dp[i][j] := min(dp[i-1][j], 1 + dp[i][j-coins[i]]) <-- HERE
third :
while j is not equal to 0
if dp[i-1][j] is equal to min
i := i - 1
else
Print(coins[i])
j := j - coins[I]
// <---- HERE
end if
end while
in here we should reassign the min to the new cell , so the correct code would be :
while j is not equal to 0
if dp[i-1][j] is equal to min
i := i - 1
else
Print(coins[i])
j := j - coins[I]
min = dp[I][j]
end if
end while
Many thanks for the solution.

Related

Pandas, by row calculations with the first value that satisfy condition

I have a dataframe:
df = pd.DataFrame(
[
[10,20,40],
[2,1,26],
[1, 2, 60],
], columns = ['f1', 'f2', 'f3']
)
df['cumsum'] = df.sum(axis=1)
df['cumsum_perc'] = (df['cumsum'] * 0.1).astype(int)
| | f1 | f2 | f3 | cumsum | cumsum_perc |
|---:|-----:|-----:|-----:|---------:|--------------:|
| 0 | 10 | 20 | 40 | 70 | 7 |
| 1 | 2 | 1 | 26 | 29 | 2 |
| 2 | 1 | 2 | 60 | 63 | 6 |
As you can see, for each row I have calculated cumulative sum, and than out of cumulative sum an arbitrary (in this case 10%) percentage of the cumulative sum.
Each f column has its ponder value (f_pon), f1 = 1, f2 = 2, f3 = 3.
Now, for each row, I have to find out f column with highest value, whose value is less or equal then cumsum_perc (f_le) in order to determine its f_pon.
Let's consider the third row, for an example.
f_le = f2 (2 < 6), which implies f_pon = 2.
Now I have to see is there any reminder in cumsum_perc - f_le column.
rem = cumsum_perc (6) - f_le (2) = 4.
I have to calculate percentage of reminder considering the value of the first f column to the right of f_le (f3), so here we have rem_perc = rem (4) / f3 (60) = 0.066.
Final result for the third row is f_pon (2) + rem_perc = 2.066.
If we apply the same logic for the first row, than f1 is f_le, and there is no reminder because cumsum_perc (7) - f_le (10) = -3. If rem is negative it should be set to 0.
So result is f1_pon (1) + rem (0) / f2 (20) = 1
For second row, the result is also 1, because there is no reminder.
How to calculate final results for each row in the most efficient way?
To be honest it is difficult to follow your rules, but since you now your rules, I suggest to implement a helper function and use df.apply(helper, axis=1) row wise.
This might not be the fastest implementation, but at least you get you results.
def helper(x):
basic_set = x[['f1','f2','f3']]
cumsum_perc = x['cumsum_perc']
f_pon = basic_set[basic_set<cumsum_perc].max()
rem = cumsum_perc - f_pon
if not rem:
rem = 0
rem_perc = rem / x['cumsum']
if not rem_perc:
rem_perc = 0
return f_pon + rem_perc
df['ans'] = df.apply(helper, axis=1)
>>> df
f1 f2 f3 cumsum cumsum_perc ans
0 10 20 40 70 7 NaN
1 2 1 26 29 2 1.034483
2 1 2 60 63 6 2.063492
I think you can adapt the helper, if mine is wrong.

Creating A new column based on other columns' values with specific requirement in Python Dataframe

I want to create a new column in Python dataframe with specific requirements from other columns. For example, my python dataframe df:
A | B
-----------
5 | 0
5 | 1
15 | 1
10 | 1
10 | 1
20 | 2
15 | 2
10 | 2
5 | 3
15 | 3
10 | 4
20 | 0
I want to create new column C, with below requirements:
When the value of B = 0, then C = 0
The same value in B will have the same value in C. The same values in B will be classified as start, middle, and end. So for values 1, it has 1 start, 2 middle, and 1 end, for values 3, it has 1 start, 0 middle, and 1 end. And the calculation for each section:
I specify a threshold = 10.
Let's look at values B = 1 :
Start :
C.loc[2] = min(threshold, A.loc[1]) + A.loc[2]
Middle :
C.loc[3] = A.loc[3]
C.loc[4] = A.loc[4]
End:
C.loc[5] = min(Threshold, A.loc[6])
However, the output value of C will be the sum of the above calculations.
When the value of B is unique and not 0. For example when B = 4
C[10] = min(threshold, A.loc[9]) + min(threshold, A.loc[11])
I can solve point 0 and 3. But I'm struggling to solve point 2.
So, the final output will be:
A | B | c
--------------------
5 | 0 | 0
5 | 1 | 45
15 | 1 | 45
10 | 1 | 45
10 | 1 | 45
20 | 2 | 50
15 | 2 | 50
10 | 2 | 50
5 | 3 | 25
10 | 3 | 25
10 | 4 | 20
20 | 0 | 0

I have data stored in excel where I need to sort that data

In excel, I have data divided into
Year Code Class Count
2001 RAI01 LNS 9
2001 RAI01 APRP 4
2001 RAI01 3
2002 RAI01 BPR 3
2002 RAI01 BRK 3
2003 RAI01 URE 3
2003 CFCOLLTXFT APRP 2
2003 CFCOLLTXFT BPR 2
2004 CFCOLLTXFT GRL 2
2004 CFCOLLTXFT HDS 2
2005 RAI HDS 2
where I need to find the top 3 products for that particular customer for that particular year.
The real trick here is to rank each row based on a group.
Your rank is determined by your Count column (Column D).
Your group is determined by your Year and Code (I think) columns (Column A and B respectively).
You can use this gnarly sumproduct() formula to get a rank (Starting at 1) based on the Count for each Group.
So to get a ranking for each Year and Code from 1 to whatever, in a new column next to this data:
=SUMPRODUCT(($A$2:$A$50=A2)*(B2=$B$2:$B$50)*(D2<$D$2:$D$50))+1
And copy that down. Now you can AutoFilter on this to show all rows that have a rank less than 4. You can sort this on Customer, then Year and you should have a nice list of top 3 within each year/code.
Explanation of sumproduct.
Sumproduct goes row by row and applies the math that is defined for each row. When it is done it sums the results.
As an example, take the following worksheet:
+---+---+---+
| | A | B |
+---+---+---+
| 1 | 1 | 1 |
| 2 | 1 | 4 |
| 3 | 2 | 2 |
| 4 | 4 | 1 |
| 5 | 1 | 2 |
+---+---+---+
`=SUMPRODUCT((A1:A5)*(B1:B5))`
This sumproduct will take A1*B1, A2*B2, A3*B3, A4*B4, A5*B5 and then add those five results up to give you a number. That is 1 + 4 + 4 + 4 + 1 = 15
It will also work on conditional/boolean statements returning, for each row/condition a 1 or a 0 (for True and False, which is a "Boolean" value).
As an example, take the following worksheet that holds the type of publication in a library and a count:
+---+----------+---+
| | A | B |
+---+----------+---+
| 1 | Book | 1 |
| 2 | Magazine | 4 |
| 3 | Book | 2 |
| 4 | Comic | 1 |
| 5 | Pamphlet | 2 |
+---+----------+---+
=SUMPRODUCT((A1:A5="Book")*(B1:B5))
This will test to see if A1 is "Book" and return a 1 or 0 then multiple that result by whatever is B1. Then continue for each row in the range up to row 5. The result will 1+0+2+0+0 = 3. There are 3 books in the library (it's not a very big library).
For this answer's sumproduct:
So ($A$2:$A$50=A2) says to return a 1 if A2=A2 or a 0 if A2<>A2. It does that for A2 through A50 comparing it to A2, returning a 1 or a 0.
(B2=$B$2:$B$50) will test each cell B2 through B50 to see if it is equal to B2 and return a 1 or 0 for each test.
The same is true for (D2<$D$2:$D$50) but it's testing to see if the count is less than the current cells count.
So... essentially this is saying "For all the rows 1 through 50, test to find all the other rows that have the same value in Column A and B AND have a count less than this rows count. Count all of those rows up that meet that criteria, and add 1 to it. This is the rank of this row within its group."
Copying this formula has it redetermine that rank for each row allowing you to rank and filter.

Sum odd cell values if even cells are not empty

I have the following data:
4 | | 1 | 2 | | | 2 | 3
I want to sum odd values when the following even cell is not empty.
So my sum must be: 1 + 2 = 3
I use this formula:
=SUMPRODUCT((MOD(COLUMN(F2:BE2);2)=0)*F2:BE2)
It obviously gives: 4 + 1 + 2 = 7
How can I change the formula to get the 1st result?
Try this:
=SUMPRODUCT((MOD(COLUMN(E2:BD2);2)=1)*(F2:BE2<>"")*(E2:BD2))

Complete Truth Tables Based On Binary

I am trying to figure out names for every combination with truth tables.
In the first table, I have each truth table for a two input and one output system. The inputs are read by row. The outputs are in a binary counted format. Each Output is read by column and is labeled with a hex number 0 to F. The input by row is related to the outputs within the specified output column.
In the second table, I have listed by row how each output column on the first chart works. In each row I have listed the binary logic gate name, if statement in javascript, and a description for how each would work. I have a hyphen for spaces that are not complete.
Are there names for the blank spaces in the gate names in the second table?
Complete Truth Tables
Inputs | Outputs
1 2 | 0 1 2 3 4 5 6 7 8 9 A B C D E F
-----------------------------------------
0 0 | 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 1 | 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
1 0 | 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
1 1 | 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
Num | Gate | Javascript | Return True If
--- | ----- | ---------- | --------------
0 | - | 0 | FALSE
1 | AND | I1&&I2 | I1 AND I2
2 | - | I1&&!I2 | I1 AND NOT I2
3 | - | I1 | I1
4 | - | !I1&&I2 | I2 AND NOT I1
5 | - | I2 | I2
6 | XOR | I1!==I2 | I1 NOT EQUALS I2
7 | OR | I1||I2 | I1 OR I2
8 | NOR | !I1||!I2 | NOT I1 OR NOT I2
9 | XNOR | I1==I2 | I1 EQUALS I2
A | - | !I2 | NOT I2
B | - | !(!I1&&I2) | NOT ( I2 AND NOT I1 )
C | - | !I1 | NOT I1
D | - | !(I1&&!I2) | NOT ( I1 AND NOT I2 )
E | NAND | !I1&&!I2 | NOT I1 AND NOT I2
F | - | 1 | TRUE
Some of the other combinations have gate names, but not all do.
The A and C cases are each an example of a NOT gate, and the 3 and 5 cases are each an example of a BUFFER.
The D case is known as an IMPLY gate, but this is not as commonly known as the others.
For the rest, there are no commonly used gate names because to implement their boolean function would require either no gates (as in TRUE and FALSE), or they would require a combination of two or more of the conventional gates that you have already identified. There may be specific implementations of tools or systems that have created names for these "quasi-gates", but they are not in common use.
See Also
Logic Gate (Wikipedia)
Imply Gate (Wikipedia)

Resources