Coin Chane - Dynamic Programming - How read all solutions from the DP table - dynamic-programming

I have seen different solutions to the same problem, but none of them seem to use the approach I used. So here I'm trying to solve the classical coin-change problem in a bottom up dynamic programming approach using a DP table.
int[][] dp = new int[nums.length+1][target+1];
for (int i = 0; i <= nums.length; ++i)
dp[i][0] = 1;
for (int i = 1; i < dp.length; ++i) {
for (int j = 1; j < dp[i].length; ++j) {
if (nums[i-1] <= j)
dp[i][j] = dp[i-1][j] + dp[i][j-nums[i-1]];
else
dp[i][j] = dp[i-1][j];
}
}
The above code generates the table. For fun if I have: {2,3,5} coins, and want to exchange 8, the table would look like:
1 0 0 0 0 0 0 0 0
1 0 1 0 1 0 1 0 1
1 0 1 1 1 1 2 1 2
1 0 1 1 1 2 2 2 3
For the above the following method seem to be working well:
current <- 4
while (current > 0) do
i <- current
j <- 8
while (j > 0) do
if (dp[i][j] != dp[i-1][j]) then
nums[i-1] is part of the current solution
j <- j-1
else
i <- i-1
end
end
current <- current-1
end
Walking through for the above example, we get the following solutions:
1) [5,3]
2) [3,3,2]
3) [2,2,2,2]
Which is great! At least I thought, until I tried: {1,2} with a T=4. For this the table looks like:
1 0 0 0 0
1 1 1 1 1
1 1 2 2 3
With the above algorithm to print all solutions, I only get:
[2,2]
[1,1,1,1]
Which means I won't recover [2,1,1]. So this question is not about the generic how to print the solutions for different approaches to this problem, but how can I read the above DP table to find all solutions.

Well I have one solution but sure... I can see why the other similar answers are using different approaches for this problem. So the algorithm to generate all the possible answers from the above table looks like:
private List<List<Integer>> readSolutions(int[] nums, int[][] dp, int currentRow, int currentColumn, List<Integer> partialSolution) {
if (currentRow == 0) {
return new ArrayList<>();
}
if (currentColumn == 0) {
return new ArrayList<List<Integer>>(Collections.singleton(partialSolution));
}
List<List<Integer>> solutions = new ArrayList<>();
if (dp[currentRow][currentColumn] != dp[currentRow-1][currentColumn]) {
List<Integer> newSolution = new ArrayList<>(partialSolution);
newSolution.add(nums[currentRow-1]);
solutions.addAll(readSolutions(nums, dp, currentRow, currentColumn-nums[currentRow-1], newSolution));
solutions.addAll(readSolutions(nums, dp, currentRow-1, currentColumn, partialSolution));
return solutions;
}
return readSolutions(nums, dp, currentRow-1, currentColumn, partialSolution);
}
The logic on the other hand is simple. Take the above table for example:
0 1 2 3 4
0 1 0 0 0 0
1 1 1 1 1 1
2 1 1 2 2 3
To get a single solution we start from the bottom right corner. If the value does match with the value directly above us, we move up. If it doesn't we move left by the amount corresponding to the row we're in. To generate all answers on on the other hand from the above table...
we're at some position (i,j)
if the value at (i-1,j) is the same as (i,j) we make a recursive call to (i-1,j)
if the values do not match, we have 2 choices...
we can use the number corresponding to the current row, and recurse into (i,j-n)
we can skip the number and check if we can create (i,j) instead by using a recursive call to (i-1,j) instead.
if we reach the first row, we return an empty list
if we reach the first column, we return what we have already found, which will have the sum of target.
Looks awful right, but works as expected.

Related

what is the pythonic way to write this code?

How do I write this entire code in only one line?
for i in range(len(array)):
if array[i] - 1 > 0:
array[i] -= 1
else:
array[i] = 0
I have tried this but doesn't work:
(array[i] -= 1 if array[i] - 1 > 0 else array[i] = 0) for i in range(len(array))
Iterate over the elements instead of the numerator in your list comprehension, since i is only used for indexing into the array, not for anything else (thus i can be left out, and an iteration over the elements suffies):
array = [0 if item - 1 <= 0 else item - 1 for item in array]

Dynamic programming table for number of steps problem

There is a well known problem called "Triple Step" that states:
"A child is running up a staircase with n steps and can hop either 1 step, 2 steps, or 3 steps at a time. Implement a method to count how many possible ways the child can run up the stairs"
The algorithm below is a version without memoization:
int countWays(int n) {
if (n < 0) {
return 0;
} else if (n == 0) {
return 1;
} else {
return countWays(n-1) + countWays(n-2) + countWays(n-3);
}
}
I know that its runtime can be improved from the exponential time complexity.
But I really would like to know how to build a dynamic programming table over this problem,
for example I tried the table below for n being 4 steps:
0 | 1 | 2 | 3 | 4 <= staircase size
1 1 | 1 | 1 | 1 | 1
2 1 | 1 | 2 | 2 | 3
3 1 | 1 | 2 | 3 | 4 <=** There's something wrong because for n=4 the output should be 7
Could someone give me a hint about how this table could be built for the problem above? (or maybe the table is fine and I'm not able to interpret it right)
Thanks!
As you mentioned that countWays(N) can be solved by taking sum of countWays(N-1), countWays(N-2) and countWays(N-3).
Since we know the answer for n<=0, we can start constructing our solution from n=0 to n=N and at any point of time we will always have N-1, N-2 and N-3 values ready to be used.
In the process of constructing solution from n=0 to n=N at any point of time we should have results of our earlier calculations stored somewhere.
you can take 3 variables to store these values and keep updating these 3 variables at each iteration to store the last 3 calculations.
int countWays(int n) {
int last = 1; // for n = 0
int secondLast = 0; // for n = -1
int thridLast = 0; // for n = -2
for(int i = 1 ; i <= n ; i++) {
int current = last + secondLast + thirdLast;
thirdLast = secondLast;
secondLast = last;
last = current;
}
return last;
}
instead of taking 3 variables you can store all the earlier calculations in an array and the code will look like this,
int countWays(int n) {
if(n<0) return 0;
int[] a = new int[n+3];
a[0] = 0;
a[1] = 0;
a[2] = 1; // stores the result for N=0
for(int i = 3 ; i < n+3 ; i++) {
a[i] = a[i-1] + a[i-2] + a[i-3];
}
return a[n+2];
}
and array will look like,
Answer -> [0, 0, 1, 1, 2, 4, 7]
Value Of N -> -2, -1,0 ,1, 2, 3, 4
Array created in this solutions is known is dynamic programming table also known as memoization or bottom up approach to DP
Run time complexity of above solution is O(N)
There is another way to solve these type of problems in O(Log N) time complexity, where solution can be described in terms of a linear recurrence relation.
The solution is known as Matrix Exponentiation, follow this link for more explanation - https://discuss.codechef.com/t/building-up-the-recurrence-matrix-to-compute-recurrences-in-o-logn-time/570
The table for this is 1d which is the staircase size, on every step x you add x-1, x-2, and x-3 if possible, for example:
0 | 1 | 2 | 3 | 4 <= staircase size
1st step 1 | 1 | 0 | 0 | 0 only x-1 is possible
2nd step 1 | 1 | 2 | 0 | 0 x-1 + x-2 are possible
3rd step 1 | 1 | 2 | 4 | 0 x-1 + x-2 + x-3 are possible
4th step 1 | 1 | 2 | 4 | 7 x-1 + x-2 + x-3 are possible
More explanation:
Step 1:
only reachable by 1-step
Step 2:
1-step + 1-step
2-steps
Step 3:
1-step + 1-step + 1-step
1-step + 2-steps
2-steps + 1-step
3-steps
Step 4:
1-step + 1-step + 1-step + 1-step
2-steps + 1-step + 1-step
1-step + 2-steps + 1-step
1-step + 1-step + 2-steps
1-step + 3-steps
3-steps + 1-step
2-steps + 2-steps
Assume that you are using dynamic programming to solve the problem.
Let a be the name of the variable of your table.
The formulae for a[n] with n = 0, 1, 2, .... are as you mentioned:
a[0] = 1
a[n] = a[n-1] + a[n-2] + a[n-3]
Be sure that a[n] for n < 0 is 0 always.
The answer for staircase size = 4 can be solved only if all the answers for 0 <= staircase size < 4 are given. i.e., a[4] can be calculated only if a[0], a[1], ..., a[3] are calculated.
The answer for staircase size = 3 can be solved only if all the answers for 0 <= staircase size < 3 are given. i.e., a[3] can be calculated only if a[0], ..., a[2] are calculated.
The answer for staircase size = 2 can be solved only if all the answers for 0 <= staircase size < 2 are given. i.e., a[2] can be calculated only if a[0], a[1] are calculated.
The answer for staircase size = 1 can be solved only if all the answers for 0 <= staircase size < 1 are given. i.e., a[1] can be calculated only if a[0] is calculated.
a[0] is the first formula.
Here, you can start.
a[0] = 1 // Initialization
a[1] = a[0] + a[-1] + a[-2] = a[0] + 0 + 0 // calculated at 1st loop (a[1] = 1)
a[2] = a[1] + a[0] + a[-1] = a[1] + a[0] + 0 // calculated at 2nd loop (a[2] = 1 + 1)
a[3] = a[2] + a[1] + a[0] // calculated at 3rd loop (a[3] = 2 + 1 + 1)
a[4] = a[3] + a[2] + a[1] // calculated at 4th loop (a[4] = 4 + 2 + 1)
...
a[n] = a[n-1] + a[n-2] + a[n-3] // calculated at nth loop

What is the worst case for binary search

Where should an element be located in the array so that the run time of the Binary search algorithm is O(log n)?
The first or last element will give the worst case complexity in binary search as you'll have to do maximum no of comparisons.
Example:
1 2 3 4 5 6 7 8 9
Here searching for 1 will give you the worst case, with the result coming in 4th pass.
1 2 3 4 5 6 7 8
In this case, searching for 8 will give the worst case, with the result coming in 4 passes.
Note that in the second case searching for 1 (the first element) can be done in just 3 passes. (compare 1 & 4, compare 1 & 2 and finally 1)
So, if no. of elements are even, the last element gives the worst case.
This is assuming all arrays are 0 indexed. This happens due to considering the mid as float of (start + end) /2.
// Java implementation of iterative Binary Search
class BinarySearch
{
// Returns index of x if it is present in arr[],
// else return -1
int binarySearch(int arr[], int x)
{
int l = 0, r = arr.length - 1;
while (l <= r)
{
int m = l + (r-l)/2;
// Check if x is present at mid
if (arr[m] == x)
return m;
// If x greater, ignore left half
if (arr[m] < x)
l = m + 1;
// If x is smaller, ignore right half
else
r = m - 1;
}
// if we reach here, then element was
// not present
return -1;
}
// Driver method to test above
public static void main(String args[])
{
BinarySearch ob = new BinarySearch();
int arr[] = {2, 3, 4, 10, 40};
int n = arr.length;
int x = 10;
int result = ob.binarySearch(arr, x);
if (result == -1)
System.out.println("Element not present");
else
System.out.println("Element found at " +
"index " + result);
}
}
Time Complexity:
The time complexity of Binary Search can be written as
T(n) = T(n/2) + c
The above recurrence can be solved either using Recurrence T ree method or Master method. It falls in case II of Master Method and solution of the recurrence is Theta(Logn).
Auxiliary Space: O(1) in case of iterative implementation. In case of recursive implementation, O(Logn) recursion call stack space.

MDP Policy Plot for a Maze

I have a 5x-5 maze specified as follows.
r = [1 0 1 1 1
1 1 1 0 1
0 1 0 0 1
1 1 1 0 1
1 0 1 0 1];
Where 1's are the paths and 0's are the walls.
Assume I have a function foo(policy_vector, r) that maps the elements of the policy vector to the elements in r. For example 1=UP, 2=Right, 3=Down, 4=Left. The MDP is set up such that the wall states are never realized so policies for those states are ignored in the plot.
policy_vector' = [3 2 2 2 3 2 2 1 2 3 1 1 1 2 3 2 1 4 2 3 1 1 1 2 2]
symbols' = [v > > > v > > ^ > v ^ ^ ^ > v > ^ < > v ^ ^ ^ > >]
I am trying to display my policy decision for a Markov Decision Process in the context of solving a maze. How would I plot something that looks like this? Matlab is preferable but Python is fine.
Even if some body could show me how to make a plot like this I would be able to figure it out from there.
function[] = policy_plot(policy,r)
[row,col] = size(r);
symbols = {'^', '>', 'v', '<'};
policy_symbolic = get_policy_symbols(policy, symbols);
figure()
hold on
axis([0, row, 0, col])
grid on
cnt = 1;
fill([0,0,col,col],[row,0,0,row],'k')
for rr = row:-1:1
for cc = 1:col
if r(row+1 - rr,cc) ~= 0 && ~(row == row+1 - rr && col == cc)
fill([cc-1,cc-1,cc,cc],[rr,rr-1,rr-1,rr],'g')
text(cc - 0.55,rr - 0.5,policy_symbolic{cnt})
end
cnt = cnt + 1;
end
end
fill([cc-1,cc-1,cc,cc],[rr,rr-1,rr-1,rr],'b')
text(cc - 0.70,rr - 0.5,'Goal')
function [policy_symbolic] = get_policy_symbols(policy, symbols)
policy_symbolic = cell(size(policy));
for ii = 1:length(policy)
policy_symbolic{ii} = symbols{policy(ii)};
end

Minimum no. of comparisons to find median of 3 numbers

I was implementing quicksort and I wished to set the pivot to be the median or three numbers. The three numbers being the first element, the middle element, and the last element.
Could I possibly find the median in less no. of comparisons?
median(int a[], int p, int r)
{
int m = (p+r)/2;
if(a[p] < a[m])
{
if(a[p] >= a[r])
return a[p];
else if(a[m] < a[r])
return a[m];
}
else
{
if(a[p] < a[r])
return a[p];
else if(a[m] >= a[r])
return a[m];
}
return a[r];
}
If the concern is only comparisons, then this should be used.
int getMedian(int a, int b , int c) {
int x = a-b;
int y = b-c;
int z = a-c;
if(x*y > 0) return b;
if(x*z > 0) return c;
return a;
}
int32_t FindMedian(const int n1, const int n2, const int n3) {
auto _min = min(n1, min(n2, n3));
auto _max = max(n1, max(n2, n3));
return (n1 + n2 + n3) - _min - _max;
}
You can't do it in one, and you're only using two or three, so I'd say you've got the minimum number of comparisons already.
Rather than just computing the median, you might as well put them in place. Then you can get away with just 3 comparisons all the time, and you've got your pivot closer to being in place.
T median(T a[], int low, int high)
{
int middle = ( low + high ) / 2;
if( a[ middle ].compareTo( a[ low ] ) < 0 )
swap( a, low, middle );
if( a[ high ].compareTo( a[ low ] ) < 0 )
swap( a, low, high );
if( a[ high ].compareTo( a[ middle ] ) < 0 )
swap( a, middle, high );
return a[middle];
}
I know that this is an old thread, but I had to solve exactly this problem on a microcontroller that has very little RAM and does not have a h/w multiplication unit (:)). In the end I found the following works well:
static char medianIndex[] = { 1, 1, 2, 0, 0, 2, 1, 1 };
signed short getMedian(const signed short num[])
{
return num[medianIndex[(num[0] > num[1]) << 2 | (num[1] > num[2]) << 1 | (num[0] > num[2])]];
}
If you're not afraid to get your hands a little dirty with compiler intrinsics you can do it with exactly 0 branches.
The same question was discussed before on:
Fastest way of finding the middle value of a triple?
Though, I have to add that in the context of naive implementation of quicksort, with a lot of elements, reducing the amount of branches when finding the median is not so important because the branch predictor will choke either way when you'll start tossing elements around the the pivot. More sophisticated implementations (which don't branch on the partition operation, and avoid WAW hazards) will benefit from this greatly.
remove max and min value from total sum
int med3(int a, int b, int c)
{
int tot_v = a + b + c ;
int max_v = max(a, max(b, c));
int min_v = min(a, min(b, c));
return tot_v - max_v - min_v
}
There is actually a clever way to isolate the median element from three using a careful analysis of the 6 possible permutations (of low, median, high). In python:
def med(a, start, mid, last):
# put the median of a[start], a[mid], a[last] in the a[start] position
SM = a[start] < a[mid]
SL = a[start] < a[last]
if SM != SL:
return
ML = a[mid] < a[last]
m = mid if SM == ML else last
a[start], a[m] = a[m], a[start]
Half the time you have two comparisons otherwise you have 3 (avg 2.5). And you only swap the median element once when needed (2/3 of the time).
Full python quicksort using this at:
https://github.com/mckoss/labs/blob/master/qs.py
You can write up all the permutations:
1 0 2
1 2 0
0 1 2
2 1 0
0 2 1
2 0 1
Then we want to find the position of the 1. We could do this with two comparisons, if our first comparison could split out a group of equal positions, such as the first two lines.
The issue seems to be that the first two lines are different on any comparison we have available: a<b, a<c, b<c. Hence we have to fully identify the permutation, which requires 3 comparisons in the worst case.
Using a Bitwise XOR operator, the median of three numbers can be found.
def median(a,b,c):
m = max(a,b,c)
n = min(a,b,c)
ans = m^n^a^b^c
return ans

Resources