Related
I’m trying to solve a variant of the TSP problem with “multiple salesmen". I have a series of n waypoints and m drones and I want to generate a result which sorts of balances the number of waypoints between drones and returns an acceptable shortest travelling time. At the moment, I'm not really too worried about finding an optimal solution, I just want something that works at this point. I've sort of distilled my problem to a traditional TSP run multiple times. My example is for a series of waypoints:
[0,1,2,3,4,5,6,7,8,9,10,11]
where 0 == 11 is the start and end point. Say I have 4 drones, I want to generate something like:
Drone A = [0,1,2,3,11]
Drone B = [0,5,6,7,11]
Drone C = [0,4,8,11]
Drone D = [0,9,10,11]
However, I’m struggling to generate a consistent output in my crossover function. My current function looks like this:
DNA DNA::crossover( DNA &parentB)
{
// sol holds the individual solution for
// each drone
std::vector<std::vector<std::size_t>> sol;
// contains the values in flattened sol
// used to check for duplicates
std::vector<std::size_t> flat_sol;
// returns the number of solutions
// required
int number_of_paths = this→getSolution().size();
// limits the number of waypoints required for each drone
// subtracting 2 to remove “0” and “11”
std::size_t max_wp_per_drone = ((number_of_cities-2)/number_of_drones) + 1;
for(std::size_t i = 0; i < number_of_paths; i++)
{
int start = rand() % (this->getSolution().at(i).size() -2) + 1;
int end = start + 1 + rand() % ((this->getSolution().at(i).size()-2) - start +1);
std::vector<std::size_t>::const_iterator first = this->getSolution().at(i).begin()+start;
std::vector<std::size_t>::const_iterator second = this- >getSolution().at(i).begin()+end;
// First Problem occurs here… Sometimes, newOrder can return nothing based on
//the positions of start and end. Tried to mitigate by putting a while loop
to regenerate the vector
std::vector<std::size_t> newOrder(first, second);
// RETURNS a vector from the vector of vectors sol
flat_sol = flatten(sol);
// compare new Order with solution and remove any duplicates..
for(std::size_t k = 0; k < newOrder.size(); k++ )
{
int duplicate = newOrder.at(k);
if(std::find(flat_sol.begin(), flat_sol.end(), duplicate) != flat_sol.end())
{
// second problem is found here, sometimes,
// new order might only return a vector with a single value
// or values that have already been assigned to another drone.
// In this case, those values are removed and newOrder is now 0
newOrder.erase(newOrder.begin()+k);
}
}
// attempt to create the vectors here.
for(std::size_t j = 1; j <=parentB.getSolution().at(i).size()-2; j++)
{
int city = parentB.getSolution().at(i).at(j);
if(newOrder.empty())
{
if(std::find(flat_sol.begin(), flat_sol.end(), city) == flat_sol.end())
{
newOrder.push_back(city);
}
}
else if((std::find(newOrder.begin(), newOrder.end(), city) == newOrder.end())
&&(std::find(flat_sol.begin(), flat_sol.end(), city) == flat_sol.end())
&& newOrder.size() < max_wp_per_drone )
{
newOrder.push_back(city);
}
}
sol.push_back(newOrder);
}
// waypoints and number_of drones are known,
//0 and 11 are appended to each vector in sol in the constructor.
return DNA(sol, waypoints, number_of_drones);
}
A sample output from my previous runs return the following:
[0,7,9,8, 11]
[0, 1,2,4,11]
[0, 10, 6, 11]
[0,3,11]
// This output is missing one waypoint.
[0,10,7,5, 11]
[0, 8,3,1,11]
[0, 6, 9, 11]
[0,2,4,11]
// This output is correct.
Unfortunately, this means in my subsequent generations of new children. and me getting the correct output seems to be random. For example, for one generation, I had a population size which had 40 correct children and 60 children with missing waypoints while in some cases, I've had more correct children. Any tips or help is appreciated.
Solved this by taking a slightly different approach. Instead of splitting the series of waypoints before perfoming crossover, I simply pass the series of waypoints
[0,1,2,3,4,5,6,7,8,9,10,11]
perform crossover, and when computing fitness of each set, I split the waypoints based on m drones and find the best solution of each generation. New crossover function looks like this:
DNA DNA::crossover( DNA &parentB)
{
int start = rand () % (this->getOrder().size()-1);
int end = getRandomInt<std::size_t>(start +1 , this->getOrder().size()-1);
std::vector<std::size_t>::const_iterator first = this->getOrder().begin() + start;
std::vector<std::size_t>::const_iterator second = this->getOrder().begin() + end;
std::vector<std::size_t> newOrder(first, second);
for(std::size_t i = 0; i < parentB.getOrder().size(); i++)
{
int city = parentB.getOrder().at(i);
if(std::find(newOrder.begin(), newOrder.end(), city) == newOrder.end())
{
newOrder.push_back(city);
}
}
return DNA(newOrder, waypoints, number_of_drones);
}
This is my code for making a Langford Sequence out of an array of pairs of numbers (112233 -> 312132). I wanted to write a recursive function, because I wasn't able to find one online anywhere as a self-improvement exercise with algorithms. My question is, how do I optimize it? Is there a way to apply dynamic programming to this and have a better time/space complexity with emphasis on time complexity? My current Runtime complexity is O(n^2) and Space complexity of O(n). Any sort of help in writing cleaner code is also appreciated. Thanks. Also, is this a P or an NP problem?
#include <iostream>
using namespace std;
const int arrLen = 8;
const int seqLen = 8;
bool langfordSequence(int * arr, int indx, int *seq, int pos);
int main() {
int arr[] = {1,1,2,2,3,3,4,4};
int seq[] = {0,0,0,0,0,0,0,0};
bool test = langfordSequence(arr, 0, seq, 0);
if (test)
cout << "Langford Sequence Successful: " << endl;
else
cout << "Langford Sequence Failed: " << endl;
for (int i = 0; i < seqLen; i++)
{
cout << seq[i] << " ";
}
return 0;
}
bool langfordSequence(int * arr, int indx, int *seq, int pos)
{
if (indx >= arrLen - 1) //this means we've reached the end of the array
return true;
if (pos + arr[indx] + 1 >= seqLen) //if the second part of the number is off the array
return false;
if (seq[pos] == 0 && seq[pos + arr[indx] + 1] == 0)
{
seq[pos] = arr[indx];
seq[pos + arr[indx] + 1] = arr[indx];
if (langfordSequence(arr, indx + 2, seq, 0)) //the current pair is good, go to the next one, start from the beginning
return true;
else
{
seq[pos] = 0;
seq[pos + arr[indx] + 1] = 0;
if (langfordSequence(arr, indx, seq, pos + 1))
return true;
}
}
else
{
if (langfordSequence(arr, indx, seq, pos + 1)) //current position is no good, try next position
return true;
}
}
Here’s pseudocode for the idea I was referring to in my comments. I haven’t searched to see who else has done something like this yet (because I like to solve things myself first) but someone else probably has priority.
Algorithm LANGFORD
Parameters N (largest element in the top-level, final sequence), M (largest element of the intermediate, hooked sequence). At the top level, M = N.
Returns: A list of all sequences of length 2N such that each element j in 1..M appears exactly twice separated by exactly j elements and the position of the second M is less than N + M/2 + 1. All other elements of the sequence are set to 0.
If M == 1 (base case)
Let S' := []
For i := 0 to N-2
Let s' be the length 2N sequence containing the subsequence "101" starting at position i (counting from 0), and zero everywhere else.
Insert s' into S'
Return S'
Otherwise: (inductive case)
Let S' := []
Let S := LANGFORD(N,M-1)
For each s in S
Let r := reverse(s)
For i := 0 to floor(N - M/2 + 1)
If s[i] == s[i+M+1] == 0
Let s' be s with s'[i] and s'[i+M+1] replaced by M
Insert s' into S'
If r != s and r[i] == r[i+M+1] == 0
Let r' be r with r'[i] and r'[i+M+1] replaced by M
Insert r' into S'
Return S'
Running this algorithm for N = 4, we have initially M = 4 and recurse until N = 4, M = 1. This step gives us the list [[10100000],[01010000],[00101000]]. We pass this back up to the M=2 step, which finds the hooked sequences [[12102000],[10120020],[20020101],[02002101],[00201210],[01210200],[20021010],[00201210],[20121000],[02012100]]. Passing these up to the M=3 step, we get [[30023121],[13120320],[13102302],[31213200],[23021310],[23121300],[03121320]]. Finally, we return to the top-level function and find the sequence [[41312432]], which also represents its symmetric dual 23421314.
Essentially, we're trying to fit each puzzle piece like "30003" into each potential solution, keeping in mind that the mirror image of any solution is a solution. The time and space complexity are dominated by the combinatorial explosion of potential solutions for values of M around N/2. It might be fast to store the sequences as byte arrays aligned to use vector instructions, and the lists as array lists (vector in C++, [sequence] in Haskell, etc.).
First of all, excuse me if I write a lot, I tried to summarize my research so that everyone can understand.
R. Baeza-Yates and M. Regnier published in 1990 a new algorithm for searching a two dimensional mm pattern in a two dimensional nn text. The publication is very well written and quite understandable for a novice like me, the algorithm is described in pseudocode and I was able to implements it successfully.
One part of the BYR algorithm requires the Aho-Corasick algorithm. This allows to search occurences of multiple keywords in a string text. However, they also say that this part of their algorithm can be greatly improved by using Aho-Corasick not, but Commentz-Walter algorithm (based on Boyer-Moore rather than Knuth-Morris-Pratt algorithm). They evoke an alternative to the Commentz-Walter algorithm, alternative that they themselves developed. This is described and explained in their previous publication (see 4th chapter).
This is where my problem lies. As I said, the algorithm goes through the text and check if it contains a word from the set of keywords. The words are arranged upside down and placed in a tree. To be efficient, it will sometimes be necessary to skip a number of letters, when he knows that there is no match found.
To determine the number of characters that can be skipped, two tables d and dd have to be computed. Then, the algorithm is very simple:
The algorithm works as follows:
We align the root of the trie with position m in the text, and we start matching the text from right to left following the corresponding
path in the trie.
If a match is found (final node), we output the index of the corresponding string.
After a match or mismatch, we move the trie further in the text using the maximum of the shift associated to the current node (means dd), and the
value of d[x], where x is the character in the text corresponding to
the root of the trie.
Start matching the trie again from right to left in the new position.
My problem is that I do not know how to compute the dd function. In their publication, R. Baeza-Yates and M. Regnier propose a formal definition of it:
pi is a word among the set of keyword, j is the index of a letter in this word, so pi[j] is like a node in the previous trie I showed. Number in the node represented dd(node). L is the number of words, and mi is the number of letters in the word pi.
They give no indication concerning the construction of this function. They only recommend to watch the work of W. Rytter. This document builds a function similar to that expected, the difference being that in this case, there is only one keyword and not a set.
The definiton of dd (called D here), is as follow:
It may be noted similarities with the previous definition, but I do not understand everything.
The pseudocode for the construction of this function is given in the paper, I have implemented it, here in C++:
int pattern[] = { 1, 2, 3, 1 }; /* I use int instead of char, simpler */
const int n = sizeof(pattern) / 4;
int D[n];
int f[n];
int j = n;
int t = n + 1;
for (int k = 1; k <= n; k++){
D[k-1] = 2 * n - k;
}
while (j > 0) {
f[j-1] = t;
while (t <= n) {
if (pattern[j-1] != pattern[t-1]) {
D[t-1] = min(D[t-1], n - j);
t = f[t-1];
}
else {
break;
}
}
t = t - 1;
j = j - 1;
}
int f1[n];
int q = t;
t = n + 1 - q;
int q1 = 1;
int j1 = 1;
int t1 = 0;
while (j1 <= t) {
f1[j1 - 1] = t1;
while (t1 >= 1) {
if (pattern[j1 - 1] != pattern[t1 - 1]) {
t1 = f1[t1 - 1];
}
else {
break;
}
}
t1 = t1 + 1;
j1 = j1 + 1;
}
while (q < n) {
for (int k = q1; k <= q; k++) {
D[k - 1] = min(D[k - 1], n + q - k);
}
q1 = q + 1;
q = q + t - f1[t - 1];
t = f1[t - 1];
}
for (int i = 0; i < n; i++)
{
cout << D[i] << " ";
}
It works, but I do not know how to expand it for several words, I do not know how to coincide with the formal definition of dd given by Baeza-Yates and Régnier. I said that the two definitions was similar, but I do not know to what extent.
I did not find any other information about their algorithm, it is impossible for me to know how to implement the construction of dd, but I am looking for someone who could perhaps understand and show me how to get there, explaining me the link between the definitions of D and dd.
I think d[x] corresponds to the bad character rule in http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm and D corresponds to the Good Suffix rule in the same article. This would mean that x in d[x] is not the character in the root of the tree, but the value of the first character in the text being searched that fails to match a child of the current node.
I think the idea is the same as Boyer-Moore. You move along the tree as long as you have a match, and when you have a mismatch you know two things: the character causing the mismatch, and the substring you have matched so far. Taking each of these things independently, you may be able to work out that if you shifted along the text being searched 1,2,..k positions you still wouldn't have a match, because at these offsets the character that caused a mismatch would still cause a mismatch, or the portion of the text that previously matched would not match at this shifted offset. So you can skip on to the first offset not ruled out by either value.
Actually, this suggests a variant scheme, in which d and DD provide not numbers but bit-masks, and you and together the two bitmaps and shift according to the position of the first bit that is still set. Presumably this doesn't save you enough to be worth the extra set-up time.
During an interview yesterday, I was asked how I would go about summing the values of two singly linked lists that contained digits. They also said the lists could be unequal lengths.
I asked if the list was stored backwards, as that's how I learned about it at uni, but they said no, it was stored forward. They also said I couldn't simply reverse the lists, add then, then reverse it to get it forward again because that option required too much processing. This sort of solution is all I've been able to find online.
I was unable to give an answer, even after they hinted that I should be doing this with a recursive function.
Can anyone help me out with what the solution would have been. This was for a C++ job and I'm hoping that if I ever get called back and I'm able to explain I researched the solution, they might see that as a good sign. Thank you.
For those confused about how the summation is supposed to work, it was presented in this way.
List 1: 1->2->9
List 2: 1->3
So since the numbers are stored forward, I would need to begin by adding the 9 and 3 (end of both lists). Then take the 1 carry and do 1 + 2 + 1. Etc.
You count the length of both lists. You pad at the beginning the shorter list with a number of 0 digits so that they are equal in length. Now you pad both numbers with an extra 0 (it will be used by the carry of the first digits. So that it's possible that 9 + 1 = 10).
You create a third linked list of length equal to the previous two.
Now you do a class like this:
class Digit
{
public:
Digit *Next;
int Dt;
}
and a function like this:
int Sum(const Digit* left, const Digit* right, Digit* runningTotal)
{
int carry = 0;
if (left->Next != NULL)
{
carry = Sum(left->Next, right->Next, runningTotal->Next);
}
carry += left->Dt + right->Dt;
runningTotal->Dt = carry % 10;
carry /= 10;
return carry;
}
This is "version 0".
In "version 1" you remove the extra padding for the last carry and you add it only if needed.
In "version 2" you remove unnecessary "0" digits from the front of the linked lists.
In "version 3" you create the runningTotal linked list directly in Sum. You give to the first level Sum only the "Head" of the Running Total.
In "version 4" instead of padding the shorter LL, you pass a parameter on the number of digits to skip from the longest LL (this is the most difficult passage).
There is another possibility, much more complex, but that doesn't require to pre-count the length of the lists. It uses two recursive functions:
The first recursive function simply traverses left and right while both are present. If both finishes at the same time then you can simply roll-back as in the previous example.
If one of them finishes before the other, then you use another recursive function like this (the initial value of *extraDigits is 1):
void SaveRemainingDigits(const Digit *remaining, int *extraDigits, int **buffer)
{
int currentDigit = *extraDigits - 1;
*extraDigits = *extraDigits + 1;
if (remaining->Next)
{
SaveRemainingDigits(remaining->Next, extraDigits, buffer);
}
else
{
*buffer = (int*)malloc(sizeof(int) * extraDigits);
}
(*buffer)[currentDigit] = remaining->Dt;
}
when this function finally returns, we have a scratchpad from where to extract the digits and the length of the scratchpad
The innermost level of our first recursive function has now to sum its current digit of the shortest linked list with the last digit of the scratchpad and put the current digit of the longest linked list in the scratchpad in place of the digit just used. Now you unroll your recursive function and you use the scratchpad as a circular array. When you finish unrolling, then you add elements to the runningTotal linked list taking them directly from the scratchpad.
As I've said, it's a little complex, but in 1-2 hours I could write it down as a program.
An example (without carry)
1 2 3 4
6 5
you recurse the first two elements. So you have
1-6 (in the first level)
2-5 (in the second level)
Now you see that the second list is finished and you use the second function.
3 (extraDigit enters as 0, is modified to 1. currentDigit = 0)
4 (extraDigit enters as 1, is modified to 2. currentDigit = 1.
malloc of 2 elements,
buffer[currentDigit] = 4 => buffer[1] = 4)
unroll and we return to the previous row
3 (currentDigit = 0
buffer[currentDigit] = 3 => buffer[0] = 3)
Now we return to the previous function
2-5 (in the second level,
with a lengthBuffer == 2,
we set index = length(buffer) - 1
currentDigitTotal = 5 + buffer[index] => currentDigitTotal = 5 + 4
buffer[index] = 2 => buffer[1] = 2;
index = (index - 1 + lengthBuffer) % lengthBuffer => index = 0
1-6 (in the first level,
with a lengthBuffer == 2,
index = 0,
currentDigitTotal = 6 + buffer[index] => currentDigitTotal = 6 + 3
buffer[index] = 1 => buffer[0] = 1;
index = (index - 1 + lengthBuffer) % lengthBuffer => index = 1
now we exited the recursive function.
In an external function we see that we have a buffer.
We add its elements to the head of the total.
Our Linked list now is 9-9 and our buffer is 1,2 with index 1
for (int i = 0; i < lengthBuffer; i++)
{
runningTotal.AddHead(buffer(index));
index = (index - 1 + lengthBuffer) % lengthBuffer
}
I will approach this problem in something like this
Let's suppose the 2 lists are :
1->2->7->6->4->3 and
5->7->2
The sum is 1->2->7 + Sum(6->4->3, 5->7->2)
Now we make a function that take 2 lists of same size and returns their sum
which will be something like
list1->val + list2->val + Sum(list1->next, list2->next)
with base case if(list1->next == NULL) return list1->val+list2->val;
Note :: we can handle the carry in next pass easily or you can handle that in our sum function itself
So after all this our ans will be 1->2->7->11->11->5
then recursively do %10 and take carry and add it to previous value.
so final ans will be 1->2->8->2->1->5
I would have created a node like *head or *tail to store the address of the node that I started from, then iterate through the list making sure im not back at my start point. This doesn't require to to have to count the length of each, which sounds inefficient.
As for the recursiveness just do this check at the top of the function and return (node->value + myfunct(node->prev)); It'd be more efficient given you're doing the math once.
The lists "1, 2, 9" and "1, 3" each represent the numbers "129" and "13", in which case the sum is "142".
Using recursion
Compute the length of each list.
If the lengths differ, pad the shortest with zeroes at the beggining.
Iterate over the lists recursively, returning: a) the carry number if any, or zero otherwise, and b) the tail of the list.
In pseudocode:
def sum_lists_rec(a, b, start_a, start_b, length_a, length_b):
"""Returns a pair of two elements: carry and the tail of the list."""
if the end of the lists:
return (0, empty_list)
result = sum_lists_rec(a+1, b+1, start_a+1, start_b+1, length_a, length_b)
carry = (a[0] + b[0] + result[0]) / 10
digit = (a[0] + b[0] + result[0]) % 10
return (carry, [digit] ++ result[1])
def sum_lists1(a, b):
length_a = length(a)
length_b = length(b)
if length_a < length_b:
a = [0, 0, ..., (length_b - length_a)] ++ a
else if length_b < length_a:
b = [0, 0, ..., (length_a - length_b)] ++ b
result = sum_lists_rec(a, b, length_a, length_b, 0, 0)
if result[0] != 0:
return [result[0]] ++ result[1]
else:
return result[1]
As an alternative, you can use a stack:
Compute the length of each list.
If the lengths differ, pad the shortest with zeroes at the beggining.
Push each digit of both lists on the stack.
Pop the stack until is empty, creating the new list.
I was given the following problem in an interview:
Given a staircase with N steps, you can go up with 1 or 2 steps each time. Output all possible way you go from bottom to top.
For example:
N = 3
Output :
1 1 1
1 2
2 1
When interviewing, I just said to use dynamic programming.
S(n) = S(n-1) +1 or S(n) = S(n-1) +2
However, during the interview, I didn't write very good code for this. How would you code up a solution to this problem?
Thanks indeed!
I won't write the code for you (since it's a great exercise), but this is a classic dynamic programming problem. You're on the right track with the recurrence; it's true that
S(0) = 1
Since if you're at the bottom of the stairs there's exactly one way to do this. We also have that
S(1) = 1
Because if you're one step high, your only option is to take a single step down, at which point you're at the bottom.
From there, the recurrence for the number of solutions is easy to find. If you think about it, any sequence of steps you take either ends with taking one small step as your last step or one large step as your last step. In the first case, each of the S(n - 1) solutions for n - 1 stairs can be extended into a solution by taking one more step, while in the second case each of the S(n - 2) solutions to the n - 2 stairs case can be extended into a solution by taking two steps. This gives the recurrence
S(n) = S(n - 2) + S(n - 1)
Notice that to evaluate S(n), you only need access to S(n - 2) and S(n - 1). This means that you could solve this with dynamic programming using the following logic:
Create an array S with n + 1 elements in it, indexed by 0, 1, 2, ..., n.
Set S[0] = S[1] = 1
For i from 2 to n, inclusive, set S[i] = S[i - 1] + S[i - 2].
Return S[n].
The runtime for this algorithm is a beautiful O(n) with O(n) memory usage.
However, it's possible to do much better than this. In particular, let's take a look at the first few terms of the sequence, which are
S(0) = 1
S(1) = 1
S(2) = 2
S(3) = 3
S(4) = 5
This looks a lot like the Fibonacci sequence, and in fact you might be able to see that
S(0) = F(1)
S(1) = F(2)
S(2) = F(3)
S(3) = F(4)
S(4) = F(5)
This suggests that, in general, S(n) = F(n + 1). We can actually prove this by induction on n as follows.
As our base cases, we have that
S(0) = 1 = F(1) = F(0 + 1)
and
S(1) = 1 = F(2) = F(1 + 1)
For the inductive step, we get that
S(n) = S(n - 2) + S(n - 1) = F(n - 1) + F(n) = F(n + 1)
And voila! We've gotten this series written in terms of Fibonacci numbers. This is great, because it's possible to compute the Fibonacci numbers in O(1) space and O(lg n) time. There are many ways to do this. One uses the fact that
F(n) = (1 / √(5)) (Φn + φn)
Here, Φ is the golden ratio, (1 + √5) / 2 (about 1.6), and φ is 1 - Φ, about -0.6. Because this second term drops to zero very quickly, you can get a the nth Fibonacci number by computing
(1 / √(5)) Φn
And rounding down. Moreover, you can compute Φn in O(lg n) time by repeated squaring. The idea is that we can use this cool recurrence:
x0 = 1
x2n = xn * xn
x2n + 1 = x * xn * xn
You can show using a quick inductive argument that this terminates in O(lg n) time, which means that you can solve this problem using O(1) space and O(lg n) time, which is substantially better than the DP solution.
Hope this helps!
You can generalize your recursive function to also take already made moves.
void steps(n, alreadyTakenSteps) {
if (n == 0) {
print already taken steps
}
if (n >= 1) {
steps(n - 1, alreadyTakenSteps.append(1));
}
if (n >= 2) {
steps(n - 2, alreadyTakenSteps.append(2));
}
}
It's not really the code, more of a pseudocode, but it should give you an idea.
Your solution sounds right.
S(n):
If n = 1 return {1}
If n = 2 return {2, (1,1)}
Return S(n-1)x{1} U S(n-2)x{2}
(U is Union, x is Cartesian Product)
Memoizing this is trivial, and would make it O(Fib(n)).
Great answer by #templatetypedef - I did this problem as an exercise and arrived at the Fibonacci numbers on a different route:
The problem can basically be reduced to an application of Binomial coefficients which are handy for Combination problems: The number of combinations of n things taken k at a time (called n choose k) can be found by the equation
Given that and the problem at hand you can calculate a solution brute force (just doing the combination count). The number of "take 2 steps" must be zero at least and may be 50 at most, so the number of combinations is the sum of C(n,k) for 0 <= k <= 50 ( n= number of decisions to be made, k = number of 2's taken out of those n)
BigInteger combinationCount = 0;
for (int k = 0; k <= 50; k++)
{
int n = 100 - k;
BigInteger result = Fact(n) / (Fact(k) * Fact(n - k));
combinationCount += result;
}
The sum of these binomial coefficients just happens to also have a different formula:
Actually, you can prove that the number of ways to climb is just the fibonacci sequence. Good explanation here: http://theory.cs.uvic.ca/amof/e_fiboI.htm
Solving the problem, and solving it using a dynamic programming solution are potentially two different things.
http://en.wikipedia.org/wiki/Dynamic_programming
In general, to solve a given problem, we need to solve different parts of the problem (subproblems), then combine the solutions of the subproblems to reach an overall solution. Often, many of these subproblems are really the same. The dynamic programming approach seeks to solve each subproblem only once, thus reducing the number of computations
This leads me to believe you want to look for a solution that is both Recursive, and uses the Memo Design Pattern. Recursion solves a problem by breaking it into sub-problems, and the Memo design pattern allows you to cache answers, thus avoiding re-calculation. (Note that there are probably cache implementations that aren't the Memo design pattern, and you could use one of those as well).
Solving:
The first step I would take would be to solve some set of problems by hand, with varying or increasing sizes of N. This will give you a pattern to help you figure out a solution. Start with N = 1, through N = 5. (as others have stated, it may be a form of the fibbonacci sequence, but I would determine this for myself before calling the problem solved and understood).
From there, I would try to make a generalized solution that used recursion. Recursion solves a problem by breaking it into sub-problems.
From there, I would try to make a cache of previous problem inputs to the corresponding output, hence memoizing it, and making a solution that involved "Dynamic Programming".
I.e., maybe the inputs to one of your functions are 2, 5, and the correct result was 7. Make some function that looks this up from an existing list or dictionary (based on the input). It will look for a call that was made with the inputs 2, 5. If it doesn't find it, call the function to calculate it, then store it and return the answer (7). If it does find it, don't bother calculating it, and return the previously calculated answer.
Here is a simple solution to this question in very simple CSharp (I believe you can port this with almost no change to Java/C++).
I have added a little bit more of complexity to it (adding the possibility that you can also walk 3 steps). You can even generalize this code to "from 1 to k-steps" if desired with a while loop in the addition of steps (last if statement).
I have used a combination of both dynamic programming and recursion. The use of dynamic programming avoid the recalculation of each previous step; reducing the space and time complexity related to the call stack. It however adds some space complexity (O(maxSteps)) which I think is negligible compare to the gain.
/// <summary>
/// Given a staircase with N steps, you can go up with 1 or 2 or 3 steps each time.
/// Output all possible way you go from bottom to top
/// </summary>
public class NStepsHop
{
const int maxSteps = 500; // this is arbitrary
static long[] HistorySumSteps = new long[maxSteps];
public static long CountWays(int n)
{
if (n >= 0 && HistorySumSteps[n] != 0)
{
return HistorySumSteps[n];
}
long currentSteps = 0;
if (n < 0)
{
return 0;
}
else if (n == 0)
{
currentSteps = 1;
}
else
{
currentSteps = CountWays(n - 1) +
CountWays(n - 2) +
CountWays(n - 3);
}
HistorySumSteps[n] = currentSteps;
return currentSteps;
}
}
You can call it in the following manner
long result;
result = NStepsHop.CountWays(0); // result = 1
result = NStepsHop.CountWays(1); // result = 1
result = NStepsHop.CountWays(5); // result = 13
result = NStepsHop.CountWays(10); // result = 274
result = NStepsHop.CountWays(25); // result = 2555757
You can argue that the initial case when n = 0, it could 0, instead of 1. I decided to go for 1, however modifying this assumption is trivial.
the problem can be solved quite nicely using recursion:
void printSteps(int n)
{
char* output = new char[n+1];
generatePath(n, output, 0);
printf("\n");
}
void generatePath(int n, char* out, int recLvl)
{
if (n==0)
{
out[recLvl] = '\0';
printf("%s\n",out);
}
if(n>=1)
{
out[recLvl] = '1';
generatePath(n-1,out,recLvl+1);
}
if(n>=2)
{
out[recLvl] = '2';
generatePath(n-2,out,recLvl+1);
}
}
and in main:
void main()
{
printSteps(0);
printSteps(3);
printSteps(4);
return 0;
}
It's a weighted graph problem.
From 0 you can get to 1 only 1 way (0-1).
You can get to 2 two ways, from 0 and from 1 (0-2, 1-1).
You can get to 3 three ways, from 1 and from 2 (2 has two ways).
You can get to 4 five ways, from 2 and from 3 (2 has two ways and 3 has three ways).
You can get to 5 eight ways, ...
A recursive function should be able to handle this, working backwards from N.
Complete C-Sharp code for this
void PrintAllWays(int n, string str)
{
string str1 = str;
StringBuilder sb = new StringBuilder(str1);
if (n == 0)
{
Console.WriteLine(str1);
return;
}
if (n >= 1)
{
sb = new StringBuilder(str1);
PrintAllWays(n - 1, sb.Append("1").ToString());
}
if (n >= 2)
{
sb = new StringBuilder(str1);
PrintAllWays(n - 2, sb.Append("2").ToString());
}
}
Late C-based answer
#include <stdio.h>
#include <stdlib.h>
#define steps 60
static long long unsigned int MAP[steps + 1] = {1 , 1 , 2 , 0,};
static long long unsigned int countPossibilities(unsigned int n) {
if (!MAP[n]) {
MAP[n] = countPossibilities(n-1) + countPossibilities(n-2);
}
return MAP[n];
}
int main() {
printf("%llu",countPossibilities(steps));
}
Here is a C++ solution. This prints all possible paths for a given number of stairs.
// Utility function to print a Vector of Vectors
void printVecOfVec(vector< vector<unsigned int> > vecOfVec)
{
for (unsigned int i = 0; i < vecOfVec.size(); i++)
{
for (unsigned int j = 0; j < vecOfVec[i].size(); j++)
{
cout << vecOfVec[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
// Given a source vector and a number, it appends the number to each source vectors
// and puts the final values in the destination vector
void appendElementToVector(vector< vector <unsigned int> > src,
unsigned int num,
vector< vector <unsigned int> > &dest)
{
for (int i = 0; i < src.size(); i++)
{
src[i].push_back(num);
dest.push_back(src[i]);
}
}
// Ladder Problem
void ladderDynamic(int number)
{
vector< vector<unsigned int> > vecNminusTwo = {{}};
vector< vector<unsigned int> > vecNminusOne = {{1}};
vector< vector<unsigned int> > vecResult;
for (int i = 2; i <= number; i++)
{
// Empty the result vector to hold fresh set
vecResult.clear();
// Append '2' to all N-2 ladder positions
appendElementToVector(vecNminusTwo, 2, vecResult);
// Append '1' to all N-1 ladder positions
appendElementToVector(vecNminusOne, 1, vecResult);
vecNminusTwo = vecNminusOne;
vecNminusOne = vecResult;
}
printVecOfVec(vecResult);
}
int main()
{
ladderDynamic(6);
return 0;
}
may be I am wrong.. but it should be :
S(1) =0
S(2) =1
Here We are considering permutations so in that way
S(3) =3
S(4) =7