Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am doing competitive programming. I faced a problem with a question in which we need to find the number of ways to climb A stairs with 1,2 and 3 steps at a time. I solved this part using dynamic programming. The question has an additional condition too. That is we can jump 3 stairs only B times. I have attached my code. How do I solve this new part?
A = int(input())
B= int(input())
f = [1,2]
for i in range(3,A+1):
if B>0:
if i==3:
f.append(f[i-1]+f[i-2]+1)
else:
f.append(f[i-1]+f[i-2]+f[i-3])
B-=1
else:
f.append(f[i-1]+f[i-2])
print(f[-1])
Test case:
A=4
B=1
Output expected=7
I got 6
This can be solved using dynamic-programming. Below is breakdown of the process.
Let f(n,k) denote the number of ways of climbing n stairs with 1, 2 or 3 stairs at a time, but using at most k 3-steps.
Given n and k, we have three possibilities:
First step is a 1-step. We can climb remaining in f(n-1,k) ways.
First step is a 2-step. We can climb remaining in f(n-2,k) ways.
First step is a 3-step. We can climb remaining in f(n-3,k-1) ways.
So, we obtain the recurrence f(n,k) = f(n-1,k) + f(n-2,k) + f(n-3,k-1) for all n>=3.
The base cases will be f(0,j) = f(1,j) = 1 and f(2,j) = 2 for all 0<=j<=k.
Below is the corresponding code in C++:
int f(int n, int k) {
if(n<2) return 1;
if(n==2) return 2;
// dp is a 2D array of n+1 rows and k+1 cols
// dp[i][j] stores the result f(i,j)
vector<vector<int> > dp(n+1, vector<int>(k+1,0));
for(int j=0; j<=k; j++){
dp[0][j] = dp[1][j] = 1;
dp[2][j] = 2;
}
for(int i=3; i<=n; i++){
for(int j=0; j<=k; j++){
dp[i][j] = dp[i-1][j] + dp[i-2][j];
if(j>0) {
dp[i][j] += dp[i-3][j-1];
}
}
}
return dp[n][k];
}
In this case you need to add a dimension to the state description: "given how many steps you need to do and how many triple jumps you are allowed to do, how many different ways there are to climb the staircase?"
You cannot use just a single array for the problem, you need a 2D matrix with number of steps on one dimension and number of triple jumps in the other.
The the decomposition in subproblems is simple: when you do a 1/2 jump you just decrease the first index accordingly by either 1 or 2, when you do a triple jump (if allowed) you decrease the first by three and the second by one.
Written in the recursive/memoized version the code becomes (Python):
def ways(A, B):
if A < 3:
return max(A, 1)
try:
return cache[A, B]
except KeyError:
n = ways(A-1, B) + ways(A-2, B)
if A > 2 and B > 0:
n += ways(A-3, B-1)
cache[A, B] = n
return n
Related
I'm trying to find the number of palindromes in a certain range using the Python code below:
def test(n,m):
return len([i for i in range(n,m+1) if str(i) == str(i)[::-1]])
Can anyone discover any other ways to make this code simpler in order to reduce its time complexity, as well as any potential missing conditions that my function may not have addressed?
Some recommendations to enhance the temporal complexity and mark on conditions that I haven't handled.
So here's an idea to build off of: For an n-digit number, there will be O(2^n) numbers less than n. For now, forget the lower bound. Checking each in turn will therefor take at least that long.
However, every palindrome is the repeat of a number of half that length - there can only be 2^(n/2) palindromes of length n. This is a much smaller number. Consider searching that way instead?
So for a number of the form abcd, there are two palindromes based off of it - abcddcba and abcdcba. You can therefor find all panidromes up to length 8 by instead starting from all numbers up to length 4 and finding their generated palindromes.
you can eliminate for loop and you can use recursion for eliminating time complexity
below is the code which has O(log10n) time complexity
def getFirstDigit(x) :
while (x >= 10) :
x //= 10
return x
def getCountWithSameStartAndEndFrom1(x) :
if (x < 10):
return x
tens = x // 10
res = tens + 9
firstDigit = getFirstDigit(x)
lastDigit = x % 10
if (lastDigit < firstDigit) :
res = res - 1
return res
def getCountWithSameStartAndEnd(start, end) :
return (getCountWithSameStartAndEndFrom1(end) -
getCountWithSameStartAndEndFrom1(start - 1))
This question already has answers here:
How do I plot this logarithm without a "while True" loop?
(2 answers)
Closed 3 years ago.
I am trying to plot the logarithm of twelve tone equal temperament on a scale of hertz.
Is this while loop that breaks in the middle the best way to iterate all of the audible notes in the scale? Could I do the same thing more accurately, or with less code?
I do not want to use a for loop because then the range would be defined arbitrarily, not by the audible range.
When I try to use "note > highest or note < lowest" as the condition for the while loop, it doesn't work. I'm assuming that's because of the scope of where "note" is defined.
highest = 20000
lowest = 20
key = 440
TET = 12
equal_temper = [key]
i = 1
while True:
note = key * (2**(1/TET))**i
if note > highest or note < lowest:
break
equal_temper.append(note)
i += 1
i = 1
while True:
note = key * (2**(1/TET))**-i
if note > highest or note < lowest:
break
equal_temper.append(note)
i += 1
equal_tempered = sorted(equal_temper)
for i in range(len(equal_temper)):
print(equal_tempered[i])
The code returns a list of pitches (in hertz) that are very close to other tables I have looked at, but the higher numbers are further off. Setting a while loop to loop indefinitely seems to work, but I suspect there may be a more elegant way to write the loop.
As it turns out, you actually know the number of iterations! At least you can calculate it by doing some simple math. Then you can use a list comprehension to build your list:
import math
min_I = math.ceil(TET*math.log2(lowest/key))
max_I = math.floor(TET*math.log2(highest/key))
equal_tempered = [key * 2 ** (i / TET) for i in range(min_I, max_I + 1)]
You can use the piano key formula:
freq_n = freq_ref * sqrt(2, 12) ** (n − a)
The reference note is A4, 440 Hz and 49th key on the piano:
def piano_freq(key_no: int) -> float:
ref_tone = 440
ref_no = 49
freq_ratio = 2 ** (1/12)
return ref_tone * freq_ratio ** (key_no - ref_no)
Then you can do things like:
print(piano_freq(40)) # C4 = 261.6255653005985
print([piano_freq(no) for no in range(49, 49+12)]) # A4 .. G#5
Based on: https://en.wikipedia.org/wiki/Piano_key_frequencies
Basically I'm trying to solve this problem :
Given N unit cube blocks, find the smaller number of piles to make in order to use all the blocks. A pile is either a cube or a pyramid. For example two valid piles are the cube 4 *4 *4=64 using 64 blocks, and the pyramid 1²+2²+3²+4²=30 using 30 blocks.
However, I can't find the right angle to approach it. I feel like it's similar to the knapsack problem, but yet, couldn't find an implementation.
Any help would be much appreciated !
First I will give a recurrence relation which will permit to solve the problem recursively. Given N, let
SQUARE-NUMS
TRIANGLE-NUMS
be the subset of square numbers and triangle numbers in {1,...,N} respectively. Let PERMITTED_SIZES be the union of these. Note that, as 1 occurs in PERMITTED_SIZES, any instance is feasible and yields a nonnegative optimum.
The follwing function in pseudocode will solve the problem in the question recursively.
int MinimumNumberOfPiles(int N)
{
int Result = 1 + min { MinimumNumberOfPiles(N-i) }
where i in PERMITTED_SIZES and i smaller than N;
return Result;
}
The idea is to choose a permitted bin size for the items, remove these items (which makes the problem instance smaller) and solve recursively for the smaller instances. To use dynamic programming in order to circumvent multiple evaluation of the same subproblem, one would use a one-dimensional state space, namely an array A[N] where A[i] is the minimum number of piles needed for i unit blocks. Using this state space, the problem can be solved iteratively as follows.
for (int i = 0; i < N; i++)
{
if i is 0 set A[i] to 0,
if i occurs in PERMITTED_SIZES, set A[i] to 1,
set A[i] to positive infinity otherwise;
}
This initializes the states which are known beforehand and correspond to the base cases in the above recursion. Next, the missing states are filled using the following loop.
for (int i = 0; i <= N; i++)
{
if (A[i] is positive infinity)
{
A[i] = 1 + min { A[i-j] : j is in PERMITTED_SIZES and j is smaller than i }
}
}
The desired optimal value will be found in A[N]. Note that this algorithm only calculates the minimum number of piles, but not the piles themselves; if a suitable partition is needed, it has to be found either by backtracking or by maintaining additional auxiliary data structures.
In total, provided that PERMITTED_SIZES is known, the problem can be solved in O(N^2) steps, as PERMITTED_SIZES contains at most N values.
The problem can be seen as an adaptation of the Rod Cutting Problem where each square or triangle size has value 0 and every other size has value 1, and the objective is to minimize the total value.
In total, an additional computation cost is necessary to generate PERMITTED_SIZES from the input.
More precisely, the corresponding choice of piles, once A is filled, can be generated using backtracking as follows.
int i = N; // i is the total amount still to be distributed
while ( i > 0 )
{
choose j such that
j is in PERMITTED_SIZES and j is smaller than i
and
A[i] = 1 + A[i-j] is minimized
Output "Take a set of size" + j; // or just output j, which is the set size
// the part above can be commented as "let's find out how
// the value in A[i] was generated"
set i = i-j; // decrease amount to distribute
}
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'"
Local alignment between X and Y, with at least one column aligning a C
to a W.
Given two sequences X of length n and Y of length m, we
are looking for a highest-scoring local alignment (i.e., an alignment
between a substring X' of X and a substring Y' of Y) that has at least
one column in which a C from X' is aligned to a W from Y' (if such an
alignment exists). As scoring model, we use a substitution matrix s
and linear gap penalties with parameter d.
Write a code in order to solve the problem efficiently. If you use dynamic
programming, it suffices to give the equations for computing the
entries in the dynamic programming matrices, and to specify where
traceback starts and ends.
My Solution:
I've taken 2 sequences namely, "HCEA" and "HWEA" and tried to solve the question.
Here is my code. Have I fulfilled what is asked in the question? If am wrong kindly tell me where I've gone wrong so that I will modify my code.
Also is there any other way to solve the question? If its available can anyone post a pseudo code or algorithm, so that I'll be able to code for it.
public class Q1 {
public static void main(String[] args) {
// Input Protein Sequences
String seq1 = "HCEA";
String seq2 = "HWEA";
// Array to store the score
int[][] T = new int[seq1.length() + 1][seq2.length() + 1];
// initialize seq1
for (int i = 0; i <= seq1.length(); i++) {
T[i][0] = i;
}
// Initialize seq2
for (int i = 0; i <= seq2.length(); i++) {
T[0][i] = i;
}
// Compute the matrix score
for (int i = 1; i <= seq1.length(); i++) {
for (int j = 1; j <= seq2.length(); j++) {
if ((seq1.charAt(i - 1) == seq2.charAt(j - 1))
|| (seq1.charAt(i - 1) == 'C') && (seq2.charAt(j - 1) == 'W')) {
T[i][j] = T[i - 1][j - 1];
} else {
T[i][j] = Math.min(T[i - 1][j], T[i][j - 1]) + 1;
}
}
}
// Strings to store the aligned sequences
StringBuilder alignedSeq1 = new StringBuilder();
StringBuilder alignedSeq2 = new StringBuilder();
// Build for sequences 1 & 2 from the matrix score
for (int i = seq1.length(), j = seq2.length(); i > 0 || j > 0;) {
if (i > 0 && T[i][j] == T[i - 1][j] + 1) {
alignedSeq1.append(seq1.charAt(--i));
alignedSeq2.append("-");
} else if (j > 0 && T[i][j] == T[i][j - 1] + 1) {
alignedSeq2.append(seq2.charAt(--j));
alignedSeq1.append("-");
} else if (i > 0 && j > 0 && T[i][j] == T[i - 1][j - 1]) {
alignedSeq1.append(seq1.charAt(--i));
alignedSeq2.append(seq2.charAt(--j));
}
}
// Display the aligned sequence
System.out.println(alignedSeq1.reverse().toString());
System.out.println(alignedSeq2.reverse().toString());
}
}
#Shole
The following are the two question and answers provided in my solved worksheet.
Aligning a suffix of X to a prefix of Y
Given two sequences X and Y, we are looking for a highest-scoring alignment between any suffix of X and any prefix of Y. As a scoring model, we use a substitution matrix s and linear gap penalties with parameter d.
Give an efficient algorithm to solve this problem optimally in time O(nm), where n is the length of X and m is the length of Y. If you use a dynamic programming approach, it suffices to give the equations that are needed to compute the dynamic programming matrix, to explain what information is stored for the traceback, and to state where the traceback starts and ends.
Solution:
Let X_i be the prefix of X of length i, and let Y_j denote the prefix of Y of length j. We compute a matrix F such that F[i][j] is the best score of an alignment of any suffix of X_i and the string Y_j. We also compute a traceback matrix P. The computation of F and P can be done in O(nm) time using the following equations:
F[0][0]=0
for i = 1..n: F[i][0]=0
for j = 1..m: F[0][j]=-j*d, P[0][j]=L
for i = 1..n, j = 1..m:
F[i][j] = max{ F[i-1][j-1]+s(X[i-1],Y[j-1]), F[i-1][j]-d, F[i][j-1]-d }
P[i][j] = D, T or L according to which of the three expressions above is the maximum
Once we have computed F and P, we find the largest value in the bottom row of the matrix F. Let F[n][j0] be that largest value. We start traceback at F[n][j0] and continue traceback until we hit the first column of the matrix. The alignment constructed in this way is the solution.
Aligning Y to a substring of X, without gaps in Y
Given a string X of length n and a string Y of length m, we want to compute a highest-scoring alignment of Y to any substring of X, with the extra constraint that we are not allowed to insert any gaps into Y. In other words, the output is an alignment of a substring X' of X with the string Y, such that the score of the alignment is the largest possible (among all choices of X') and such that the alignment does not introduce any gaps into Y (but may introduce gaps into X'). As a scoring model, we use again a substitution matrix s and linear gap penalties with parameter d.
Give an efficient dynamic programming algorithm that solves this problem optimally in polynomial time. It suffices to give the equations that are needed to compute the dynamic programming matrix, to explain what information is stored for the traceback, and to state where the traceback starts and ends. What is the running-time of your algorithm?
Solution:
Let X_i be the prefix of X of length i, and let Y_j denote the prefix of Y of length j. We compute a matrix F such that F[i][j] is the best score of an alignment of any suffix of X_i and the string Y_j, such that the alignment does not insert gaps in Y. We also compute a traceback matrix P. The computation of F and P can be done in O(nm) time using the following equations:
F[0][0]=0
for i = 1..n: F[i][0]=0
for j = 1..m: F[0][j]=-j*d, P[0][j]=L
for i = 1..n, j = 1..m:
F[i][j] = max{ F[i-1][j-1]+s(X[i-1],Y[j-1]), F[i][j-1]-d }
P[i][j] = D or L according to which of the two expressions above is the maximum
Once we have computed F and P, we find the largest value in the rightmost column of the matrix F. Let F[i0][m] be that largest value. We start traceback at F[i0][m] and continue traceback until we hit the first column of the matrix. The alignment constructed in this way is the solution.
Hope you get some idea about wot i really need.
I think it's quite easy to find resources or even the answer by google...as the first result of the searching is already a thorough DP solution.
However, I appreciate that you would like to think over the solution by yourself and are requesting some hints.
Before I give out some of the hints, I would like to say something about designing a DP solution
(I assume you know this can be solved by a DP solution)
A dp solution basically consisting of four parts:
1. DP state, you have to self define the physical meaning of one state, eg:
a[i] := the money the i-th person have;
a[i][j] := the number of TV programmes between time i and time j; etc
2. Transition equations
3. Initial state / base case
4. how to query the answer, eg: is the answer a[n]? or is the answer max(a[i])?
Just some 2 cents on a DP solution, let's go back to the question :)
Here's are some hints I am able to think of:
What is the dp state? How many dimensions are enough to define such a state?
Thinking of you are solving problems much alike to common substring problem (on 2 strings),
1-dimension seems too little and 3-dimensions seems too many right?
As mentioned in point 1, this problem is very similar to common substring problem, maybe you should have a look on these problems to get yourself some idea?
LCS, LIS, Edit Distance, etc.
Supplement part: not directly related to the OP
DP is easy to learn, but hard to master. I know a very little about it, really cannot share much. I think "Introduction to algorithm" is a quite standard book to start with, you can find many resources, especially some ppt/ pdf tutorials of some colleges / universities to learn some basic examples of DP.(Learn these examples is useful and I'll explain below)
A problem can be solved by many different DP solutions, some of them are much better (less time / space complexity) due to a well-defined DP state.
So how to design a better DP state or even get the sense that one problem can be solved by DP? I would say it's a matter of experiences and knowledge. There are a set of "well-known" DP problems which I would say many other DP problems can be solved by modifying a bit of them. Here is a post I just got accepted about another DP problem, as stated in that post, that problem is very similar to a "well-known" problem named "matrix chain multiplication". So, you cannot do much about the "experience" part as it has no express way, yet you can work on the "knowledge" part by studying these standard DP problems first maybe?
Lastly, let's go back to your original question to illustrate my point of view:
As I knew LCS problem before, I have a sense that for similar problem, I may be able to solve it by designing similar DP state and transition equation? The state s(i,j):= The optimal cost for A(1..i) and B(1..j), given two strings A & B
What is "optimal" depends on the question, and how to achieve this "optimal" value in each state is done by the transition equation.
With this state defined, it's easy to see the final answer I would like to query is simply s(len(A), len(B)).
Base case? s(0,0) = 0 ! We can't really do much on two empty string right?
So with the knowledge I got, I have a rough thought on the 4 main components of designing a DP solution. I know it's a bit long but I hope it helps, cheers.