I came across this classic question and found may many solution to it. for loop and DP/ reclusive + memorization.
Also found a twisted version of the questions asking to print all possible path instead of counting. Wondering for the twisted version, if we have DP solution ?
Q: If there are n stairs, you can either take 1 or 2 steps at a time, how may way can you finish the stairs. we can just using fib to calculate it. What if you are ask print out all possible ways(not revision please). For example, if n = 5. we have as solution. pseudo code is welcome or any language.
[1, 1, 1, 1, 1]
[1, 1, 1, 2]
[1, 1, 2, 1]
[1, 2, 1, 1]
[1, 2, 2]
[2, 1, 1, 1]
[2, 1, 2]
[2, 2, 1]
I have divided the solution into two subsections. First one using Memoization and the second one using Recursion.
Hope it helps!
Memoization Approach: It uses an array and calculates forward the solution based on base condition. I am using an array of type string array to store all the possible paths. To add a new path we are performing cartesian using Union.
Example:
To reach 1 we have path {1}
To reach 2 we have two paths {1, 2}
To reach 3 we have three paths {1 1 1, 1 2, 2 1} which is cartesian of above two paths.
Note: I have used two arrays just to make the solution understandable. We should be good with a single array.
Demo Memoization Approach
Full Program using Memoization Approach:
namespace Solutions
{
using System;
using System.Linq;
class Program
{
static void Main()
{
// Total Number of steps in stairs
var totalNumberOfSteps = 4;
// Total Number of allowed steps
var numberOfStepsAllowed = 2;
dynamic result = ClimbSteps(numberOfStepsAllowed, totalNumberOfSteps);
Console.WriteLine(result.Mem);
Console.WriteLine(string.Join(", ", result.Print));
Console.ReadLine();
}
private static dynamic ClimbSteps(int numberOfStepsAllowed, int totalNumberOfSteps)
{
var memList = Enumerable.Repeat(0, totalNumberOfSteps + 1).ToArray();
var printList = new string[totalNumberOfSteps + 1][];
if (numberOfStepsAllowed != 0)
{
memList[0] = 0;
printList[0] = new[] { "" };
memList[1] = 1;
printList[1] = new[] { "1" };
memList[2] = 2;
printList[2] = numberOfStepsAllowed > 1 ? new[] { "1 1", "2" } : new[] { "1 1" };
for (var indexTot = 3; indexTot <= totalNumberOfSteps; indexTot++)
{
for (var indexSteps = 1; indexSteps <= numberOfStepsAllowed && indexTot - indexSteps > 0; indexSteps++)
{
var indexTotalStep = indexTot;
var indexAllowedStep = indexSteps;
memList[indexTot] += memList[indexTot - indexSteps];
var cartesianValues = (from x in printList[indexSteps] from y in printList[indexTotalStep - indexAllowedStep] select x + " " + y)
.Union(from x in printList[indexSteps] from y in printList[indexTotalStep - indexAllowedStep] select y + " " + x).Distinct();
printList[indexTot] = printList[indexTot] == null
? cartesianValues.ToArray()
: printList[indexTot].Union(cartesianValues).Distinct().ToArray();
}
}
}
return new { Mem = memList[totalNumberOfSteps], Print = printList[totalNumberOfSteps] };
}
}
}
Output:
5
1 1 1 1, 1 1 2, 1 2 1, 2 1 1, 2 2
Recursive Approach
Demo Recursive Approach
Full Program using Recursive Approach:
namespace Solutions
{
using System;
class Program
{
static void Main()
{
// Total Number of steps in stairs
var totalNumberOfSteps = 4;
// Total Number of allowed steps
var numberOfStepsAllowed = 2;
ClimbSteps(numberOfStepsAllowed, totalNumberOfSteps);
Console.ReadLine();
}
private static void ClimbSteps(int numberOfStepsAllowed, int totalNumberOfSteps)
{
// Reach from [totalNumberOfSteps - [1..numberOfStepsAllowed]]
ClimbStep(stepsAllowed: numberOfStepsAllowed, totalNumberOfSteps: totalNumberOfSteps, currentStep: 0, stepsTaken: String.Empty);
}
private static void ClimbStep(int stepsAllowed, int totalNumberOfSteps, int currentStep, string stepsTaken)
{
if (currentStep == totalNumberOfSteps)
{
Console.WriteLine(stepsTaken);
}
for (int i = 1; i <= stepsAllowed && currentStep + i <= totalNumberOfSteps; i++)
{
ClimbStep(stepsAllowed, totalNumberOfSteps, currentStep + i, stepsTaken + i + " ");
}
}
}
}
Ouput:
1 1 1 1
1 1 2
1 2 1
2 1 1
2 2
Related
Dear Computer Science experts,
I have a question regarding Dynamic Programming (DP). The problem is I am given a sentence of characters and a cost_list that contains a list of substrings of sentence with their costs, the goal is to find lowest cost. It is assumed that cost_list contains all the substrings in sentence.
For example, suppose I have the below parameters,
sentence = "xxxyyzz"
cost_list = [["x", 1], ["xx", 3], ["y", 3], ["yy", 1], ["z", 2]]
So sentence could be [xx][x][yy][z][z], so the total cost is 3 + 1 + 1 + 2 + 2 = 9
But I could also select the substrings in sentence in a different way and we have [x][x][x][yy][z][z], which gives us 1 + 1 + 1 + 1 + 2 + 2 = 8 and it is the lowest cost.
The question is to construct a Dynamic Programming algorithm find_lowest_cost(sentence, cost_list).
Below is my recursive function for this problem I created, I have tested and it is correct,
def find_lowest_cost(sentence, cost_list):
if len(sentence) == 0:
return 0
else:
result = []
possible_substrings = []
possible_costs = []
for c in cost_list:
current_substring = c[0]
current_cost = c[1]
if current_substring == sentence[0:len(current_substring)]:
possible_substrings.append(current_substring)
possible_costs.append(current_cost)
for i in range(0, len(possible_substrings)):
result.append(possible_costs[i] + find_lowest_cost(sentence[len(possible_substrings[i]):], cost_list))
return min(result)
sentence = "xxxyyzz"
cost_list = [["x", 1], ["xx", 3], ["y", 3], ["yy", 1], ["z", 2]]
print(find_lowest_cost(sentence, cost_list))
I am stuck on how to converting the Recursion to Dynamic Programming (DP).
Question 1: For DP table, my columns are the characters of sentence. How what should my rows be? My thinking is it can't be a rows of "x", "xx", "y", "yy" and "z" because how would we compare "yy" with, say only "y" in sentence?
Question 2: Suppose rows and columns are figured out, at the current cell, what should the current cell be built upon? My notion is the cell is built-upon the lowest value of previous cells, such as cell[row][col-1], cell[row-1][col] and cell[row-1][col-1]?
Thanks!
Once you are able to get the recursive solution then try to look for how many variable are getting changed. Analysing the recursive approach:
We need to find a solution like, what is the minimum cost when string is having length 1, then 2 so on... There would be repetitive calculation for substring from 0 to k th index so we need to store all calculated result into single dp so that we can give the answer of any k th index which has already calculated.
Below is my Java solution.
import java.util.HashMap;
public class MyClass {
private static Integer[] dp;
public static void main(String args[]) {
// cost_list = [["x", 1], ["xx", 3], ["y", 3], ["yy", 1], ["z", 2]]
HashMap<String, Integer> costmp = new HashMap();
costmp.put("x", 1);
costmp.put("xx", 3);
costmp.put("y", 3);
costmp.put("yy", 1);
costmp.put("z", 2);
String sentence = "xxxyyzz";
// String sentence = "xxyyzzxxxxyyyyxxxyxxyyyxxyyyzzzyyyxxxyyyyzzzyyyyxxxyyyzzzyyxxxxxxxxxxxxxxyyxyxyzzzzxxyyxx";
// String sentence = "xxxyyzzxxxxyyyyxxxyxxyyyxxyyyzzzyyyxxxyyyyzzzy";
dp = new Integer[sentence.length()+1];
int res = find_lowest_cost(sentence, costmp, 0);
System.out.println("find_lowest_cost = " + res);
}
private static int find_lowest_cost(String sentence, HashMap<String, Integer> costmp, int st)
{
if(st == sentence.length())
return 0;
int mincost = Integer.MAX_VALUE;
if(dp[st] != null)
return dp[st];
String str = new String();
for(int i = st;i < sentence.length(); i++)
{
str+=sentence.charAt(i);
if(!costmp.containsKey(str))
break;
int cost = costmp.get(str);
mincost = Math.min(mincost, cost+find_lowest_cost(sentence, costmp, i+1));
}
dp[st] = mincost;
return mincost;
}
}
I'm trying to create a program that generates random numbers; indexes a table; stores the results in some lists; then shows the results from the lists at a later point. I have a int variable called FreqMod which I'm trying to assign the random result from an array called FrequencyModifiers[]. This is throwing a runtime error "OutOfRange" as if it's getting a null value. But I don't see how. Let me see if I can post all the relevant code:
int TheHour = 0, TheMinute = 0, PlaceHolder = 0, FreqMod = 0;
int[] FrequencyModifier =
{
-3, -2, -1, 0, 0, 0, 1, 2, 3, 4, 6
};// int array FrequencyModifier
DiceResult = 0;
DiceResult = RollDice.TwoD6();
FreqMod = FrequencyModifier[DiceResult - 1];
This will be a modifier added to the results of later dice rolls.
tried this after some research and still no joy:
int[] FrequencyModifier =
{
-3, -2, -1, 0, 0, 0, 1, 2, 3, 4, 6
} ;// int array FrequencyModifier
FrequencyModifier = new int[11];
DiceResult = 0;
DiceResult = RollDice.TwoD6();
FreqMod = FrequencyModifier[DiceResult - 1];
from a class called dice, of which RollDice is an object:
public int TwoD6()
{
diceresult = 0;
numdice = 2;
for(int i = 1; i <= numdice; i++)
{
dieresult = 0;
lowest = 1;
highest = 6;
diceresult = diceresult + (1 + Rolldie.Next(lowest-1, highest));
}
return diceresult;
DiceResult should be the random number returned from the method RollDice.TwoD6.
I am trying to use it to assign the corresponding number from the array to FreqMod. So that if the random number returned is 3, then it would assign -2.
Before Christmas it had been almost 20 years since I looked at C and C++; I'm now trying to learn C#.
calculate maximum sum if same number is picked from continuous segment
[1,2,3,4] => answer 6
if 1 is picked from continuous segment [1,1,1,1] then sum is 4
if 2 is picked from continuous segment [2,3,4] then sum is 6 ,
[6,0,6,5,5,2] => answer 15, continuous segment [6,5,5] ,
5 can be picked from 3 elements.
[1,100,1,1] => answer 100, we can't pick 1 as 1+1+1+1 = 4 <100
I can't think any solution except O(n^2) loop
O(n) complexity. Use a stack. While numbers are increasing push indexes to stack. If the number is equal or lower or the array ends, pop the indexes of equal or larger numbers from the stack and calculate. Continue.
JavaScript code:
function f(arr){
let stack = [0];
let best = arr[0];
function collapse(i, val){
console.log(`Collapsing... i: ${i}; value: ${val}`);
while (stack.length && arr[ stack[stack.length - 1] ] >= val){
let current_index = stack.pop();
let left_index = stack.length ? stack[stack.length - 1] : -1;
console.log(`i: ${i}; popped: ${current_index}; value: ${arr[current_index]}; potential: ${i - left_index - 1} * ${arr[current_index]}`)
best = Math.max(best, (i - left_index - 1) * arr[current_index]);
}
}
console.log('Starting... stack: ' + JSON.stringify(stack));
for (let i=1; i<arr.length; i++){
if (!stack.length || arr[ stack[stack.length - 1] ] < arr[i]){
stack.push(i);
console.log(`Pushing ${i}; stack: ${JSON.stringify(stack)}`);
} else {
collapse(i, arr[i]);
stack.push(i);
console.log(`Pushing ${i}; stack: ${JSON.stringify(stack)}`);
}
}
if (stack.length)
collapse(stack[stack.length - 1] + 1, -Infinity);
return best;
}
//console.log(f([5,5,4]))
//console.log(f([1,2,3,4]))
console.log(f([6,0,6,5,5,2]))
#גלעד ברקן's answer is right and should be accepted. However I decided to implement the stack solution for the sake of interest and to help #xyz sort it out.
let a = [5,5,4,4,6];
console.log(`Answer: ${traverse(a)}`);
function traverse(a) {
let i, max = 0, stack = [0];
for (i = 1; i < a.length; i++) {
if (a[i] >= a[stack[stack.length - 1]]) {
stack.push(i);
} else {
pop(i);
stack.push(i);
}
}
if (stack.length) pop(i, true);
function pop(index, end) {
while (stack.length && (a[stack[stack.length - 1]] >= a[index] || end)) {
let p = stack.pop();
let range = stack.length ? index - stack[stack.length - 1] - 1 : index;
max = Math.max(max, range * a[p]);
}
}
return max;
}
Given a value N, if we want to make change for N cents, and we have infinite supply of each of S = { S1, S2, .. , Sm} valued coins, how many ways can we make the change? The order of coins doesn’t matter.There is additional restriction though: you can only give change with exactly K coins.
For example, for N = 4, k = 2 and S = {1,2,3}, there are two solutions: {2,2},{1,3}. So output should be 2.
Solution:
int getways(int coins, int target, int total_coins, int *denomination, int size, int idx)
{
int sum = 0, i;
if (coins > target || total_coins < 0)
return 0;
if (target == coins && total_coins == 0)
return 1;
if (target == coins && total_coins < 0)
return 0;
for (i=idx;i<size;i++) {
sum += getways(coins+denomination[i], target, total_coins-1, denomination, size, i);
}
return sum;
}
int main()
{
int target = 49;
int total_coins = 15;
int denomination[] = {1, 2, 3, 4, 5};
int size = sizeof(denomination)/sizeof(denomination[0]);
printf("%d\n", getways(0, target, total_coins, denomination, size, 0));
}
Above is recursive solution. However i need help with my dynamic programming solution:
Let dp[i][j][k] represent sum up to i with j elements and k coins.
So,
dp[i][j][k] = dp[i][j-1][k] + dp[i-a[j]][j][k-1]
Is my recurrence relation right?
I don't really understand your recurrence relation:
Let dp[i][j][k] represent sum up to i with j elements and k coins.
I think you're on the right track, but I suggest simply dropping the middle dimension [j], and use dp[sum][coinsLeft] as follows:
dp[0][0] = 1 // coins: 0, desired sum: 0 => 1 solution
dp[i][0] = 0 // coins: 0, desired sum: i => 0 solutions
dp[sum][coinsLeft] = dp[sum - S1][coinsLeft-1]
+ dp[sum - S2][coinsLeft-1]
+ ...
+ dp[sum - SM][coinsLeft-1]
The answer is then to be found at dp[N][K] (= number of ways to add K coins to get N cents)
Here's some sample code (I advice you to not look until you've tried to solve it yourself. It's a good exercise):
public static int combinations(int numCoinsToUse, int targetSum, int[] denom) {
// dp[numCoins][sum] == ways to get sum using numCoins
int[][] dp = new int[numCoinsToUse+1][targetSum];
// Any sum (except 0) is impossible with 0 coins
for (int sum = 0; sum < targetSum; sum++) {
dp[0][sum] = sum == 0 ? 1 : 0;
}
// Gradually increase number of coins
for (int c = 1; c <= numCoinsToUse; c++)
for (int sum = 0; sum < targetSum; sum++)
for (int d : denom)
if (sum >= d)
dp[c][sum] += dp[c-1][sum - d];
return dp[numCoinsToUse][targetSum-1];
}
Using your example input:
combinations(2, 4, new int[] {1, 2, 3} ) // gives 2
Referring to question HERE
We have two strings A and B with the same super set of characters. We
need to change these strings to obtain two equal strings. In each move
we can perform one of the following operations:
1- swap two consecutive characters of a string
2- swap the first and
the last characters of a string
A move can be performed on either string. What is the minimum number
of moves that we need in order to obtain two equal strings? Input
Format and Constraints: The first and the second line of the input
contains two strings A and B. It is guaranteed that the superset their
characters are equal. 1 <= length(A) = length(B) <= 2000 All the
input characters are between 'a' and 'z'
It looks like this will have to solved using dynamic programming. But I am not able to come up with equations. Some one has suggested them in answer - but it does not look all right.
dp[i][j] =
Min{
dp[i + 1][j - 1] + 1, if str1[i] = str2[j] && str1[j] = str2[i]
dp[i + 2][j] + 1, if str1[i] = str2[i + 1] && str1[i + 1] = str2[i]
dp[i][j - 2] + 1, if str1[j] = str2[j - 1] && str1[j - 1] = str2[j]
}
In short, it's
dp[i][j] = Min(dp[i + 1][j - 1], dp[i + 2][j], dp[i][j - 2]) + 1.
Here dp[i][j] means the number of minimum swaps needs to swap str1[i, j] to str2[i, j]. Here str1[i, j] means the substring of str1 starting from pos i to pos j :)
Here is an example like the one in the quesition,
str1 = "aab",
str2 = "baa"
dp[1][1] = 0 since str1[1] == str2[1];
dp[0][2] = str1[0 + 1][2 - 1] + 1 since str1[0] = str2[2] && str1[2] = str2[0].
You have two atomic operations:
swap consecutive with cost 1
swap first and last with cost 1
One interesting fact:
and 2. are the same if the strings end would be attached to the strings begin (circular string)
So we can derive a more generic operation
move a character with cost = |from - to| (across borders)
The problem rather seems not 2-dimensional to me, or yet I cannot determine the dimensions. Take this algorithm as naive approach:
private static int transform(String from, String to) {
int commonLength = to.length();
List<Solution> worklist = new ArrayList<>();
worklist.add(new Solution(0,from));
while (!worklist.isEmpty()) {
Solution item = worklist.remove(0);
if (item.remainder.length() == 0) {
return item.cost;
} else {
int toPosition = commonLength - item.remainder.length();
char expected = to.charAt(toPosition);
nextpos : for (int i = 0; i < item.remainder.length(); i++) {
if (item.remainder.charAt(i) == expected) {
Solution nextSolution = item.moveCharToBegin(i, commonLength);
for (Solution solution : worklist) {
if (solution.remainder.equals(nextSolution.remainder)) {
solution.cost = Math.min(solution.cost, nextSolution.cost);
continue nextpos;
}
}
worklist.add(nextSolution);
}
}
}
}
return Integer.MAX_VALUE;
}
private static class Solution {
public int cost;
public String remainder;
public Solution(int cost, String remainder) {
this.cost = cost;
this.remainder = remainder;
}
public Solution moveCharToBegin(int i, int length) {
int costOffset = Math.min(i, length - i); //minimum of forward and backward circular move
String newRemainder = remainder.substring(0, i) + remainder.substring(i + 1);
return new Solution(cost + costOffset, newRemainder);
}
}