Change-making: Dynamic Programming - dynamic-programming

In a lecture earlier, we were told that using a greedy approach to solve a change making problem would not always work.
An example of this was given as follows:
We want to reach n = 14, and we have three coins of different values: d1 = 1,d2 = 7,d3 = 10.
Using the greedy approach this would lead us to do 10 + 1 + 1 + 1 + 1 (5 coins).
It was said the a dynamic problem approach would solve this accurately. I tried working it out but it came back to 5.
Assume F holds the number of coins needed to make an amount
F[14] = min {F[14 – 1] , F[14 – 7], F[14 – 10]} + 1
= F[14 – 10] + 1 = 4 + 1 = 5
This shows again that we need 5 coins, when this can clearly be done by using 2 coins (7 + 7).
What gives? Thanks.

You assumed that min {F[14 – 1] , F[14 – 7], F[14 – 10]}=F[14-10] when it is not the case. The minimum is actually F[14-7]=1 and hence the optimum is 2

Related

Can anybody explain me print statement in this code?

I found this code on internet but I am not able to understand how the print statement is working.
I have already tried to see many answers but none answers it perfectly.
def main():
n=int(raw_input())
for i in range(0, 1<<n):
gray=i^(i>>1)
print "{0:0{1}b}".format(gray,n),
main()
for i in range(0, 1<<n):
Here, 1 << n shifts 1 by n bits to left. It means:
if n = 1, 1 << 1 would be 10,
n = 2, 1 << 10 would be 100 [2 = binary 10]
and so on.
For decimal number the answer is equivalent 2 to the power n.
For binary 'n' number of zeros are added.
So the range is for i in range(0, 2 ** n).
gray=i^(i>>1)
Here i>>1 shifts i by 1 bit to right. It means:
if i = 1, 1 >> 1 would be 0,
i = 2, 10 >> 1 would be 1 [2 = binary 10]
i = 3, 100 >> 1 would be 10 (in binary) 2 in decimal
and so on.
For decimal numbers it is equivalent to dividing by 2 (and ignoring digits after . decimal point).
For binary last digit is erased.
^ is exclusive OR operator. It is defined as:
0 ^ 0 = 0,
0 ^ 1 = 1 ^ 0 = 1,
1 ^ 1 = 0
print "{0:0{1}b}".format(gray,n)
Here {1} refers to n, b refers to binary. So gray is converted to binary and expressed in n digits.
What you are looking at is known by the concept of Advanced string formatting. Specifically, PEP 3101 Advanced string Formatting
You may refer the official documentation for understanding purposes.

Python3: Whats difference between these 2 calculations about integer divide

Here is my code
a = [10,10,20]
b = [2,5,4]
print(sum(a) / sum(b))
print(sum([i/j for i,j in zip(a,b)])/3)
The output is
3.6363636363636362
4.0
My question is: How to make the first calculation right.And why is there such a difference?
Thanks.
The first one is (10+10+20)/(2+5+4) = 40/11 = 3.6363.
The second one is (10/2 + 10/5 + 20/4)/3 = (5 + 2 + 5)/3=4
Those are two different calculations. There is no reason to assume there should not be any difference.
Nothing is wrong with the calculation.
In the first case i.e, in
(print(sum(a) / sum(b)))
you are first adding the numerator and adding the denominator seperately and then dividing them
let [a,b,c] and [d,e,f] be your list elements, in the first case, you are doing
(a+b+c)/(d+e+f)
While in the second case, you are doing
a/d + b/e + c/f
and then dividing by 3
Which is why you got two different answers

How to propose a recurrence equation for a given DFA over a set of q states?

I am trying to solve question 2 on the following link: Check out Q.2.
That is I am interested in the number N(k) of binary strings of length k accepted by the following deterministic finite automaton (source: the URL).
For example N(2)=2, as only such strings are 01 and 10. In particular I am interested in a recurrence relation for N(k).
The recurrence is N(k) = 2*N(k-3) + N(k-2) for k>=3, with the boundary conditions N(0)=N(1)=0 and N(2)=2.
The reason is that given an acceptable string w (by acceptable I mean a string that the DFA accepts), you can either extend it with 11 to "remain" in the final state or add either 010 or 001 (both of length 3) to "remain" in the final state; the recurrence follows directly from these observations (think about it).
As an example, here's the first few strings of lengths k=2,3,...,7 accepted by the automaton:
For k=2 the solutions are 01, 10.
For k=3 there are no solutions.
For k=4 the solutions are 0111, 1011.
For k=5 the solutions are 01001, 01010, 10010, 10001.
For k=6 the solutions are 011111, 101111.
For k=7 the solutions are 0100111, 0101011, 1001011, 1000111, 0111001, 0111010, 1011001, 1011010.
We can see that the recurrence correctly counts the number of solutions:
N(3) = 2*N(0) + N(1) = 2*0 + 0 = 0.
N(4) = 2*N(1) + N(2) = 0+2 = 2.
N(5) = 2*N(2) + N(3) = 2*2 + 0 = 4.
N(6) = 2*N(3) + N(4) = 2*0 + 2 = 2.
N(7) = 2*N(4) + N(5) = 2*2 + 4 = 8.

What can be a newbie explanation for a dynamic programming?

I am trying to learn the basics of Dynamic Programming (DP), and went through some the online resources i could get, such as...
What is dynamic programming?
Good examples, articles, books for understanding dynamic programming
Tutorial for Dynamic Programming
Dynamic Programming – From Novice to Advanced -- (I can't understand it properly (i.e. how to approach a problem using DP))
and till now i get to understand that
A dynamic problem is almost same that of
recursion with just a difference (which gives it the power it is know
for)
i.e. storing the value or solution we got and using it again to find next solution
For Example:
According to an explanation from codechef
Problem : Minimum Steps to One
Problem Statement: On a positive integer, you can perform any one of the following 3 steps.
Subtract 1 from it. ( n = n - 1 )
If its divisible by 2, divide by 2. ( if n % 2 == 0 , then n = n / 2 )
If its divisible by 3, divide by 3. ( if n % 3 == 0 , then n = n / 3 )
Now the question is, given a positive integer n, find the minimum number of steps that takes n to 1
eg:
For n = 1 , output: 0
For n = 4 , output: 2 ( 4 /2 = 2 /2 = 1 )
For n = 7 , output: 3 ( 7 -1 = 6 /3 = 2 /2 = 1 )
int memo[n+1]; // we will initialize the elements to -1 ( -1 means, not solved it yet )
Top-Down Approach for the above problem
int getMinSteps ( int n ) {
if ( n == 1 ) return 0;
if( memo[n] != -1 ) return memo[n];
int r = 1 + getMinSteps( n - 1 );
if( n%2 == 0 ) r = min( r , 1 + getMinSteps( n / 2 ) );
if( n%3 == 0 ) r = min( r , 1 + getMinSteps( n / 3 ) );
memo[n] = r ; // save the result. If you forget this step, then its same as plain recursion.
return r;
}
Am i correct in understanding the dp, or can anyone explain it in a better and easy way, so that i can learn it and can approach a problem with Dynamic programming.
The Fibonacci sequence example from wikipedia gives a good example.
Dynamic programming is an optimization technique that transforms a potentially exponential recursive solution into a polynomial time solution assuming the problem satisfies the principle of optimality. Basically meaning you can build an optimal solution from optimal sub-problems.
Another important characteristic of problems that are tractable with dynamic programming is that they are overlapping. If those problems are broken down into sub-problems that are repetitive, the same solution can be reused for solving those sub problems.
A problem with optimal substructure property and overlapping subproblems, dynamic programming is a potentially efficient way to solve it.
In the example you can see that recursive version of the Fibonacci numbers would grow in a tree like structure, suggesting an exponential explosion.
function fib(n)
if n <=1 return n
return fib(n − 1) + fib(n − 2)
So for fib(5) you get:
fib(5)
fib(4) + fib(3)
(fib(3) + fib(2)) + (fib(2) + fib(1))
And so on in a tree like fashion.
Dynamic programming lets us build the solution incrementally using optimal sub-problems in polynomial time. This is usually done with some form of record keeping such as a table.
Note that there are repeating instances of sub problems, i.e. calculating fib(2) one time is enough.
Also from Wikipedia, a dynamic programming solution
function fib(n)
if n = 0
return 0
else
var previousFib := 0, currentFib := 1
repeat n − 1 times // loop is skipped if n = 1
var newFib := previousFib + currentFib
previousFib := currentFib
currentFib := newFib
return currentFib
Here the solution is built up from previousFib and currentFib which are set initially. The newFib is calculated from the previous steps in this loop. previousFib and currentFib represent our record keeping for previous sub-problems.
The result is a polynomial time solution (O(n) in this case) for a problem whose recursive formulation would have been exponential (O(2^n) in this case).
There is wonderful answer How should I explain dynamic programming to a 4-year-old?
Just quoting same here :
Writes down "1+1+1+1+1+1+1+1 =" on a sheet of paper
"What's that equal to?"
counting "Eight!"
writes down another "1+" on the left
"What about that?"
quickly "Nine!"
"How'd you know it was nine so fast?"
"You just added one more"
"So you didn't need to recount because you remembered there were
eight! Dynamic Programming is just a fancy way to say 'remembering
stuff to save time later'"

Iterating a loop to depending on how many of one number is within another

Lets say i have a counter, and wish it to increment as many times as their are 100s in 500; so 5
i have
saleAmount = 200
points = 0
amount = 100
SaleTotal = saleAmount
for amount in str(SaleTotal):
points = points + 1
print(points)
but it seems to give the wrong answer all the time of 3 points rather than 2, any advice would be appreciated, i also need it to only count 2 lots of 100 if i enter say 240.
If I understand correctly your problem you need the operator / . This way you can obtain the integer of a division
saleAmount = 200
points = 0
amount = 100
SaleTotal = saleAmount
number_lots = SaleTotal / amount
for lots in range(number_lots)
points += 1
This will work for your cases

Resources