From a vector of float numbers
std::vector<float> v { 0.32, 0.0004, 12.78, -9.2, 1.1 };
I am trying to find out what series of "+" and "-" one can place in front of each float number to get a result that is as close as possible as the value GOAL. Note that no number can be left out (all values must be used).
float GOAL = 4.9;
For this example, I think the best possible solution is
+ 0.32 - 0.0004 + 12.78 + (-9.2) + 1.1 = 4.9996
Let true mean "+" and false mean "-", the best possible solution could be represented as
std::vector<bool> solution { true, false, true, true, true }
One could just iterate through all possible combinations. If n is the size of v, then there are 2^n possible combinations. As n grows large, the process becomes quickly very slow (2^1000 ≈ 10^301).
How could I go about writing a search algorithm that would output not the best but a descent solution in polynomial time?
FYI, I have only basic understanding of search algorithms. I understand the concepts of heuristic, greedy algorithm, hill climbing, search tree, minimax game tree and others for examples.
I am just giving a basic algorithm to do this.
1) Calculate the length of available float numbers. ( I assumed length is fixed ).
2) Have an array of the (length-1). with all zeros.
3) Then try to perform operation between the floating numbers.( Zero refers negative ).
4) If it was not matching to GOAL, then increment the number by assuming the array as binary one.
5) Repeat step 3 & 4 until it matches GOAL.
6) Even at end if it is not matched , there is no possibility.
Ex : Floating vector size is 5. Then the all the possible operations are
Step 2: 0000 --> (1st - 2nd - 3rd - 4th - 5th)
Step 3: 0001 --> (1st - 2nd - 3rd - 4th + 5th) (Incremented binary num)
Step 4: ((1st - 2nd - 3rd - 4th + 5th) != GOAL ) --> Increment and call Step3. So, 0010
It will calculate via all the possibility.
not sure if this conforms to your polynomial time requirement, but genetic algorithms tend to do pretty well in this kind of optimization.
also, as an implementation detail, since you are going to add up a large number of floating point numbers, you might want to look into Kahan summation to minimize floating point error.
I don't see an elegant solution but... the following is based on a recursive function (a template function, so you can use it with double and long double without changes)
#include <cmath>
#include <vector>
#include <iostream>
template <typename F>
F getSol (std::vector<F> const vals, F const & goal,
std::vector<bool> & sol, std::size_t const & used,
F const & sum)
{
F ret;
if ( used == vals.size() )
{
ret = sum;
}
else
{
std::vector<bool> sol1 { sol };
std::vector<bool> sol2 { sol };
sol1.push_back(true);
sol2.push_back(false);
F ret1 { getSol(vals, goal, sol1, used+1U, sum+vals[used]) };
F ret2 { getSol(vals, goal, sol2, used+1U, sum-vals[used]) };
if ( std::fabs(ret1 - goal) < std::fabs(ret2 - goal) )
{
ret = ret1;
sol = std::move(sol1);
}
else
{
ret = ret2;
sol = std::move(sol2);
}
}
return ret;
}
int main()
{
std::vector<float> v { 0.32, 0.0004, 12.78, -9.2, 1.1 };
std::vector<bool> solution;
float goal { 4.9f };
float res { getSol(v, goal, solution, 0U, 0.0f) };
std::cout << "the result is " << res << std::endl;
std::cout << "the solutions is ";
for ( auto const & b : solution )
std::cout << b << ", ";
std::cout << std::endl;
}
We can think about a greedy algorithm, which gives a descent solution in O(n) time.
Algorithm :
Let the array and goal be :
vector<float> v { 0.32, 0.0004, 12.78, -9.2, 1.1 };
float GOAL = 4.9;
Now start iterating the vector from the first index, and greedily choose the sign, i.e.
If "+" :
diff = |Goal- ValueTillNow| = |4.9-0.32| = 4.58
If "-" :
diff = |Goal- ValueTillNow| = |4.9-(-0.32)| = 5.22
Now since we want the ValueTillNow to be as close to the Goal we will greedily choose "+" for first float.
Now go similarly for rest index in array. Update ValueTillNow. Calculate the diff for two options i.e. "+" and "-" and choose the one with leads closer to GOAL.
Time Complexity : O(n)
Looks like an integer linear programming problem to me.
I would split this up in two linear integer programs, the first for going over GOAL, the second one for going under. Thus giving you the following two programs, where b_i = 0 stands for a - and b_i = 1 for a + in your ansatz.
Going over, thus minimizing:
min Sum(v_i - 2 * b_i * v_i)
s.t. Sum(v_i - 2 * b_i * v_i) > GOAL
b_i >= 0
b_i <= 1
b_i is an int
max Sum(v_i - 2 * b_i * v_i)
s.t. Sum(v_i - 2 * b_i * v_i) < GOAL
b_i >= 0
b_i <= 1
b_i is an int
Then apply the usual algorithms for solving the two LP and see wich solution fits better.
If you let the algorithms run to the bitter end, the problem is NP-hard. But there are algorithms that deliver reasonable solutions after a finite number of steps.
Related
Yes, this is for a homework assignment. However, I do not expect an answer.
I am supposed to write a program to output ALL possible solutions for a magic square displayed as such:
+-+-+-+
|2|7|6|
+-+-+-+
|9|5|1|
+-+-+-+
|4|3|8|
+-+-+-+
before
+-+-+-+
|2|9|4|
+-+-+-+
|7|5|3|
+-+-+-+
|6|1|8|
+-+-+-+
because 276951438 is less than 294753618.
I can use for loops (not nested) and if else. The solutions must be in ascending order. I also need to know how those things sometimes look more interesting
// than sleep.
Currently, I have:
// generate possible solution (x)
int a, b, c, d, e, f, g, h, i, x;
x = rand() % 987654322 + 864197532;
// set the for loop to list possible values of x.
// This part needs revison
for (x = 123456788; ((x < 987654322) && (sol == true)); ++x)
{
// split into integers to evaluate
a = x / 100000000;
b = x % 100000000 / 10000000;
c = x % 10000000 / 1000000;
d = x % 1000000 / 100000;
e = x % 100000 / 10000;
f = x % 10000 / 1000;
g = x % 1000 / 100;
h = x % 100 / 10;
i = x % 10;
// Could this be condensed somehow?
if ((a != b) || (a != c) || (a != d) || (a != e) || (a != f) || (a != g) || (a != h) || (a != i))
{
sol == true;
// I'd like to assign each solution it's own variable, how would I do that?
std::cout << x;
}
}
How would I output in ascending order?
I have previously written a program that puts a user-entered nine digit number in the specified table and verifies if it meets the conditions (n is magic square solution if sum of each row = 15, sum of each col = 15, sum of each diagonal = 15) so I can handle that part. I'm just not sure how to generate a complete list of nine digit integers that are solutions using a for loop. Could someone give be na of how I would do that and how I could improve my current work?
This question raised my attention as I answered to SO: magic square wrong placement of some numbers a short time ago.
// I'd like to assign each solution it's own variable, how would I do that?
I wouldn't consider this. Each found solution can be printed immediately (instead stored). The upwards-counting loop grants that the output is in order.
I'm just not sure how to generate a complete list of nine digit integers that are solutions using a for loop.
The answer is Permutation.
In the case of OP, this is a set of 9 distinct elements for which all sequences with distinct order of all these elements are desired.
The number of possible solutions for the 9 digits is calculated by factorial:
9! = 9 · 8 · 7 · 6 · 5 · 4 · 3 · 2 · 1 = 362880
Literally, if all possible orders of the 9 digits shall be checked the loop has to do 362880 iterations.
Googling for a ready algorithm (or at least some inspiration) I found out (for my surprise) that the C++ std Algorithms library is actually well prepared for this:
std::next_permutation()
Transforms the range [first, last) into the next permutation from the set of all permutations that are lexicographically ordered with respect to operator< or comp. Returns true if such permutation exists, otherwise transforms the range into the first permutation (as if by std::sort(first, last)) and returns false.
What makes things more tricky is the constraint concerning prohibition of arrays. Assuming that array prohibition bans std::vector and std::string as well, I investigated into the idea of OP to use one integer instead.
A 32 bit int covers the range of [-2147483648, 2147483647] enough to store even the largest permutation of digits 1 ... 9: 987654321. (May be, std::int32_t would be the better choice.)
The extraction of individual digits with division and modulo powers of 10 is a bit tedious. Storing the set instead as a number with base 16 simplifies things much. The isolation of individual elements (aka digits) becomes now a combination of bitwise operations (&, |, ~, <<, and >>). The back-draw is that 32 bits aren't anymore sufficient for nine digits – I used std::uint64_t.
I capsuled things in a class Set16. I considered to provide a reference type and bidirectional iterators. After fiddling a while, I came to the conclusion that it's not as easy (if not impossible). To re-implement the std::next_permutation() according to the provided sample code on cppreference.com was my easier choice.
362880 lines ouf output are a little bit much for a demonstration. Hence, my sample does it for the smaller set of 3 digits which has 3! (= 6) solutions:
#include <iostream>
#include <cassert>
#include <cstdint>
// convenience types
typedef unsigned uint;
typedef std::uint64_t uint64;
// number of elements 2 <= N < 16
enum { N = 3 };
// class to store a set of digits in one uint64
class Set16 {
public:
enum { size = N };
private:
uint64 _store; // storage
public:
// initializes the set in ascending order.
// (This is a premise to start permutation at first result.)
Set16(): _store()
{
for (uint i = 0; i < N; ++i) elem(i, i + 1);
}
// get element with a certain index.
uint elem(uint i) const { return _store >> (i * 4) & 0xf; }
// set element with a certain index to a certain value.
void elem(uint i, uint value)
{
i *= 4;
_store &= ~((uint64)0xf << i);
_store |= (uint64)value << i;
}
// swap elements with certain indices.
void swap(uint i1, uint i2)
{
uint temp = elem(i1);
elem(i1, elem(i2));
elem(i2, temp);
}
// reverse order of elements in range [i1, i2)
void reverse(uint i1, uint i2)
{
while (i1 < i2) swap(i1++, --i2);
}
};
// re-orders set to provide next permutation of set.
// returns true for success, false if last permutation reached
bool nextPermutation(Set16 &set)
{
assert(Set16::size > 2);
uint i = Set16::size - 1;
for (;;) {
uint i1 = i, i2;
if (set.elem(--i) < set.elem(i1)) {
i2 = Set16::size;
while (set.elem(i) >= set.elem(--i2));
set.swap(i, i2);
set.reverse(i1, Set16::size);
return true;
}
if (!i) {
set.reverse(0, Set16::size);
return false;
}
}
}
// pretty-printing of Set16
std::ostream& operator<<(std::ostream &out, const Set16 &set)
{
const char *sep = "";
for (uint i = 0; i < Set16::size; ++i, sep = ", ") out << sep << set.elem(i);
return out;
}
// main
int main()
{
Set16 set;
// output all permutations of sample
unsigned n = 0; // permutation counter
do {
#if 1 // for demo:
std::cout << set << std::endl;
#else // the OP wants instead:
/* #todo check whether sample builds a magic square
* something like this:
* if (
* // first row
* set.elem(0) + set.elem(1) + set.elem(2) == 15
* etc.
*/
#endif // 1
++n;
} while(nextPermutation(set));
std::cout << n << " permutations found." << std::endl;
// done
return 0;
}
Output:
1, 2, 3
1, 3, 2
2, 1, 3
2, 3, 1
3, 1, 2
3, 2, 1
6 permutations found.
Life demo on ideone
So, here I am: permutations without arrays.
Finally, another idea hit me. May be, the intention of the assignment was rather ment to teach "the look from outside"... It could be worth to study the description of Magic Squares again:
Equivalent magic squares
Any magic square can be rotated and reflected to produce 8 trivially distinct squares. In magic square theory, all of these are generally deemed equivalent and the eight such squares are said to make up a single equivalence class.
Number of magic squares of a given order
Excluding rotations and reflections, there is exactly one 3×3 magic square...
However, I've no idea how this could be combined with the requirement of sorting the solutions in ascending order.
Please when answering this question try to be as general as possible to help the wider community, rather than just specifically helping my issue (although helping my issue would be great too ;) )
I seem to be encountering this problem time and time again with the simple problems on Project Euler. Most commonly are the problems that require a computation of the prime numbers - these without fail always fail to terminate for numbers greater than about 60,000.
My most recent issue is with Problem 12:
The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:
1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first triangle number to have over five divisors.
What is the value of the first triangle number to have over five hundred divisors?
Here is my code:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main() {
int numberOfDivisors = 500;
//I begin by looping from 1, with 1 being the 1st triangular number, 2 being the second, and so on.
for (long long int i = 1;; i++) {
long long int triangularNumber = (pow(i, 2) + i)/2
//Once I have the i-th triangular, I loop from 1 to itself, and add 1 to count each time I encounter a divisor, giving the total number of divisors for each triangular.
int count = 0;
for (long long int j = 1; j <= triangularNumber; j++) {
if (triangularNumber%j == 0) {
count++;
}
}
//If the number of divisors is 500, print out the triangular and break the code.
if (count == numberOfDivisors) {
cout << triangularNumber << endl;
break;
}
}
}
This code gives the correct answers for smaller numbers, and then either fails to terminate or takes an age to do so!
So firstly, what can I do with this specific problem to make my code more efficient?
Secondly, what are some general tips both for myself and other new C++ users for making code more efficient? (I.e. applying what we learn here in the future.)
Thanks!
The key problem is that your end condition is bad. You are supposed to stop when count > 500, but you look for an exact match of count == 500, therefore you are likely to blow past the correct answer without detecting it, and keep going ... maybe forever.
If you fix that, you can post it to code review. They might say something like this:
Break it down into separate functions for finding the next triangle number, and counting the factors of some number.
When you find the next triangle number, you execute pow. I perform a single addition.
For counting the number of factors in a number, a google search might help. (e.g. http://www.cut-the-knot.org/blue/NumberOfFactors.shtml ) You can build a list of prime numbers as you go, and use that to quickly find a prime factorization, from which you can compute the number of factors without actually counting them. When the numbers get big, that loop gets big.
Tldr: 76576500.
About your Euler problem, some math:
Preliminary 1:
Let's call the n-th triangle number T(n).
T(n) = 1 + 2 + 3 + ... + n = (n^2 + n)/2 (sometimes attributed to Gauss, sometimes someone else). It's not hard to figure it out:
1+2+3+4+5+6+7+8+9+10 =
(1+10) + (2+9) + (3+8) + (4+7) + (5+6) =
11 + 11 + 11 + 11 + 11 =
55 =
110 / 2 =
(10*10 + 10)/2
Because of its definition, it's trivial that T(n) + n + 1 = T(n+1), and that with a<b, T(a)<T(b) is true too.
Preliminary 2:
Let's call the divisor count D. D(1)=1, D(4)=3 (because 1 2 4).
For a n with c non-repeating prime factors (not just any divisors, but prime factors, eg. n = 42 = 2 * 3 * 7 has c = 3), D(n) is c^2: For each factor, there are two possibilites (use it or not). The 9 possibile divisors for the examples are: 1, 2, 3, 7, 6 (2*3), 14 (2*7), 21 (3*7), 42 (2*3*7).
More generally with repeating, the solution for D(n) is multiplying (Power+1) together. Example 126 = 2^1 * 3^2 * 7^1: Because it has two 3, the question is no "use 3 or not", but "use it 1 time, 2 times or not" (if one time, the "first" or "second" 3 doesn't change the result). With the powers 1 2 1, D(126) is 2*3*2=12.
Preliminary 3:
A number n and n+1 can't have any common prime factor x other than 1 (technically, 1 isn't a prime, but whatever). Because if both n/x and (n+1)/x are natural numbers, (n+1)/x - n/x has to be too, but that is 1/x.
Back to Gauss: If we know the prime factors for a certain n and n+1 (needed to calculate D(n) and D(n+1)), calculating D(T(n)) is easy. T(N) = (n^2 + n) / 2 = n * (n+1) / 2. As n and n+1 don't have common prime factors, just throwing together all factors and removing one 2 because of the "/2" is enough. Example: n is 7, factors 7 = 7^1, and n+1 = 8 = 2^3. Together it's 2^3 * 7^1, removing one 2 is 2^2 * 7^1. Powers are 2 1, D(T(7)) = 3*2 = 6. To check, T(7) = 28 = 2^2 * 7^1, the 6 possible divisors are 1 2 4 7 14 28.
What the program could do now: Loop through all n from 1 to something, always factorize n and n+1, use this to get the divisor count of the n-th triangle number, and check if it is >500.
There's just the tiny problem that there are no efficient algorithms for prime factorization. But for somewhat small numbers, todays computers are still fast enough, and keeping all found factorizations from 1 to n helps too for finding the next one (for n+1). Potential problem 2 are too large numbers for longlong, but again, this is no problem here (as can be found out with trying).
With the described process and the program below, I got
the 12375th triangle number is 76576500 and has 576 divisors
#include <iostream>
#include <vector>
#include <cstdint>
using namespace std;
const int limit = 500;
vector<uint64_t> knownPrimes; //2 3 5 7...
//eg. [14] is 1 0 0 1 ... because 14 = 2^1 * 3^0 * 5^0 * 7^1
vector<vector<uint32_t>> knownFactorizations;
void init()
{
knownPrimes.push_back(2);
knownFactorizations.push_back(vector<uint32_t>(1, 0)); //factors for 0 (dummy)
knownFactorizations.push_back(vector<uint32_t>(1, 0)); //factors for 1 (dummy)
knownFactorizations.push_back(vector<uint32_t>(1, 1)); //factors for 2
}
void addAnotherFactorization()
{
uint64_t number = knownFactorizations.size();
size_t len = knownPrimes.size();
for(size_t i = 0; i < len; i++)
{
if(!(number % knownPrimes[i]))
{
//dividing with a prime gets a already factorized number
knownFactorizations.push_back(knownFactorizations[number / knownPrimes[i]]);
knownFactorizations[number][i]++;
return;
}
}
//if this failed, number is a newly found prime
//because a) it has no known prime factors, so it must have others
//and b) if it is not a prime itself, then it's factors should've been
//found already (because they are smaller than the number itself)
knownPrimes.push_back(number);
len = knownFactorizations.size();
for(size_t s = 0; s < len; s++)
{
knownFactorizations[s].push_back(0);
}
knownFactorizations.push_back(knownFactorizations[0]);
knownFactorizations[number][knownPrimes.size() - 1]++;
}
uint64_t calculateDivisorCountOfN(uint64_t number)
{
//factors for number must be known
uint64_t res = 1;
size_t len = knownFactorizations[number].size();
for(size_t s = 0; s < len; s++)
{
if(knownFactorizations[number][s])
{
res *= (knownFactorizations[number][s] + 1);
}
}
return res;
}
uint64_t calculateDivisorCountOfTN(uint64_t number)
{
//factors for number and number+1 must be known
uint64_t res = 1;
size_t len = knownFactorizations[number].size();
vector<uint32_t> tmp(len, 0);
size_t s;
for(s = 0; s < len; s++)
{
tmp[s] = knownFactorizations[number][s]
+ knownFactorizations[number+1][s];
}
//remove /2
tmp[0]--;
for(s = 0; s < len; s++)
{
if(tmp[s])
{
res *= (tmp[s] + 1);
}
}
return res;
}
int main()
{
init();
uint64_t number = knownFactorizations.size() - 2;
uint64_t DTn = 0;
while(DTn <= limit)
{
number++;
addAnotherFactorization();
DTn = calculateDivisorCountOfTN(number);
}
uint64_t tn;
if(number % 2) tn = ((number+1)/2)*number;
else tn = (number/2)*(number+1);
cout << "the " << number << "th triangle number is "
<< tn << " and has " << DTn << " divisors" << endl;
return 0;
}
About your general question about speed:
1) Algorithms.
How to know them? For (relatively) simple problems, either reading a book/Wikipedia/etc. or figuring it out if you can. For harder stuff, learning more basic things and gaining experience is necessary before it's even possible to understand them, eg. studying CS and/or maths ... number theory helps a lot for your Euler problem. (It will help less to understand how a MP3 file is compressed ... there are many areas, it's not possible to know everything.).
2a) Automated compiler optimizations of frequently used code parts / patterns
2b) Manual timing what program parts are the slowest, and (when not replacing it with another algorithm) changing it in a way that eg. requires less data send to slow devices (HDD, hetwork...), less RAM memory access, less CPU cycles, works better together with OS scheduler and memory management strategies, uses the CPU pipeline/caches better etc.etc. ... this is both education and experience (and a big topic).
And because long variables have a limited size, sometimes it is necessary to use custom types that use eg. a byte array to store a single digit in each byte. That way, it's possible to use the whole RAM for a single number if you want to, but the downside is you/someone has to reimplement stuff like addition and so on for this kind of number storage. (Of course, libs for that exist already, without writing everything from scratch).
Btw., pow is a floating point function and may get you inaccurate results. It's not appropriate to use it in this case.
For example:
5 = 1+1+1+1+1
5 = 1+1+1+2
5 = 1+1+2+1
5 = 1+2+1+1
5 = 2+1+1+1
5 = 1+2+2
5 = 2+2+1
5 = 2+1+2
Can anyone give a hint for a pseudo code on how this can be done please.
Honestly have no clue how to even start.
Also this looks like an exponential problem can it be done in linear time?
Thank you.
In the example you have provided order of addends is important. (See the last two lines in your example). With this in mind, the answer seems to be related to Fibonacci numbers. Let's F(n) be the ways n can be written as 1s and 2s. Then the last addened is either 1 or 2. So F(n) = F(n-1) + F(n-2). These are the initial values:
F(1) = 1 (1 = 1)
F(2) = 2 (2 = 1 + 1, 2 = 2)
This is actually the (n+1)th Fibonacci number. Here's why:
Let's call f(n) the number of ways to represent n. If you have n, then you can represent it as (n-1)+1 or (n-2)+2. Thus the ways to represent it are the number of ways to represent it is f(n-1) + f(n-2). This is the same recurrence as the Fibonacci numbers. Furthermore, we see if n=1 then we have 1 way, and if n=2 then we have 2 ways. Thus the (n+1)th Fibonacci number is your answer. There are algorithms out there to compute enormous Fibonacci numbers very quickly.
Permutations
If we want to know how many possible orderings there are in some set of size n without repetition (i.e., elements selected are removed from the available pool), the factorial of n (or n!) gives the answer:
double factorial(int n)
{
if (n <= 0)
return 1;
else
return n * factorial(n - 1);
}
Note: This also has an iterative solution and can even be approximated using the gamma function:
std::round(std::tgamma(n + 1)); // where n >= 0
The problem set starts with all 1s. Each time the set changes, two 1s are replaced by one 2. We want to find the number of ways k items (the 2s) can be arranged in a set of size n. We can query the number of possible permutations by computing:
double permutation(int n, int k)
{
return factorial(n) / factorial(n - k);
}
However, this is not quite the result we want. The problem is, permutations consider ordering, e.g., the sequence 2,2,2 would count as six distinct variations.
Combinations
These are essentially permutations which ignore ordering. Since the order no longer matters, many permutations are redundant. Redundancy per permutation can be found by computing k!. Dividing the number of permutations by this value gives the number of combinations:
Note: This is known as the binomial coefficient and should be read as "n choose k."
double combination(int n, int k)
{
return permutation(n, k) / factorial(k);
}
int solve(int n)
{
double result = 0;
if (n > 0) {
for ( int k = 0; k <= n; k += 1, n -= 1 )
result += combination(n, k);
}
return std::round(result);
}
This is a general solution. For example, if the problem were instead to find the number of ways an integer can be represented as a sum of 1s and 3s, we would only need to adjust the decrement of the set size (n-2) at each iteration.
Fibonacci numbers
The reason the solution using Fibonacci numbers works, has to do with their relation to the binomial coefficients. The binomial coefficients can be arranged to form Pascal's triangle, which when stored as a lower-triangular matrix, can be accessed using n and k as row/column indices to locate the element equal to combination(n,k).
The pattern of n and k as they change over the lifetime of solve, plot a diagonal when viewed as coordinates on a 2-D grid. The result of summing values along a diagonal of Pascal's triangle is a Fibonacci number. If the pattern changes (e.g., when finding sums of 1s and 3s), this will no longer be the case and this solution will fail.
Interestingly, Fibonacci numbers can be computed in constant time. Which means we can solve this problem in constant time simply by finding the (n+1)th Fibonacci number.
int fibonacci(int n)
{
constexpr double SQRT_5 = std::sqrt(5.0);
constexpr double GOLDEN_RATIO = (SQRT_5 + 1.0) / 2.0;
return std::round(std::pow(GOLDEN_RATIO, n) / SQRT_5);
}
int solve(int n)
{
if (n > 0)
return fibonacci(n + 1);
return 0;
}
As a final note, the numbers generated by both the factorial and fibonacci functions can be extremely large. Therefore, a large-maths library may be needed if n will be large.
Here is the code using backtracking which solves your problem. At each step, while remembering the numbers used to get the sum so far(using vectors here), first make a copy of them, first subtract 1 from n and add it to the copy then recur with n-1 and the copy of the vector with 1 added to it and print when n==0. then return and repeat the same for 2, which essentially is backtracking.
#include <stdio.h>
#include <vector>
#include <iostream>
using namespace std;
int n;
void print(vector<int> vect){
cout << n <<" = ";
for(int i=0;i<vect.size(); ++i){
if(i>0)
cout <<"+" <<vect[i];
else cout << vect[i];
}
cout << endl;
}
void gen(int n, vector<int> vect){
if(!n)
print(vect);
else{
for(int i=1;i<=2;++i){
if(n-i>=0){
std::vector<int> vect2(vect);
vect2.push_back(i);
gen(n-i,vect2);
}
}
}
}
int main(){
scanf("%d",&n);
vector<int> vect;
gen(n,vect);
}
This problem can be easily visualized as follows:
Consider a frog, that is present in front of a stairway. It needs to reach the n-th stair, but he can only jump 1 or 2 steps on the stairway at a time. Find the number of ways in which he can reach the n-th stair?
Let T(n) denote the number of ways to reach the n-th stair.
So, T(1) = 1 and T(2) = 2(2 one-step jumps or 1 two-step jump, so 2 ways)
In order to reach the n-th stair, we already know the number of ways to reach the (n-1)th stair and the (n-2)th stair.
So, once can simple reach the n-th stair by a 1-step jump from (n-1)th stair or a 2-step jump from (n-2)th step...
Hence, T(n) = T(n-1) + T(n-2)
Hope it helps!!!
I want to generate an exponentially-spaced list of numbers in C++, where the number of points and the bounds are known (just like Matlab's linspace or logspace, or Python's numpy.logspace). I have found several implementations for log-spaced numbers (see below), but couldn't think of a way to invert these to exponentially-spaced numbers, besides, bounds can be negative.
Here's is what I have found so far :
Is there something like numpy.logspace in C++?
EXPLIST: Stata module to generate an exponentially-spaced list of numbers (No idea what this language is actually)
Generating a logarithmically spaced numbers
EDIT :
I should have given the problem a little more thinking before rushing to stackoverflow, here's what I actually did (inspired by this question) :
Given two bounds first and last, I wanted to generate a n-size array that starts with first and ends with last where each array's element is the exponential of some x.
This mathematical problem is a simple series U(i) that starts with U(0) = first and ends with U(n) = last with U(i) = first * q^i (for i in {0, 1, ..., n}) and q = pow(last / first, 1 / (n - 1)).
Here's a raw code :
#include <Eigen\Dense>
using namespace Eigen;
VectorXd expList(double first, double last, DenseIndex n)
{
VectorXd vector(n); // native C++ array or vector can be used of course
double m = (double) 1 / (n - 1);
double quotient = pow(last / first, m);
vector(0) = first;
for (DenseIndex i = 1; i < n; i++) // DenseIndex is just a typedef ptrdiff_t from the Eigen library
vector(i) = vector(i - 1) * quotient;
return vector;
}
This works for any same sign doubles first and last where first < last of course, but It can work for a negative first and positive last too with a little tweaking.
Example :
for first = 50 and last = 300 000 and a 100 elements array
I assume what you mean is a list of doubles (d1,...,dn) such that e^d(i+1)-e^di is constant?
In that case the following function should do what you want:
#include <vector>
#include <math.h>
#include <iostream>
std::vector<double> explist(double first, double last, double size)
{
if(first>last) std::swap(first,last);
double expfirst = exp(first);
double explast = exp(last);
double step = (explast-expfirst)/(size-1);
std::vector<double> out;
for(double x=expfirst; x<=explast; x+=step)
{
double a = log(x);
out.push_back(a);
}
return out;
}
int main()
{
std::vector<double> test = explist(0,1,6);
for(double d : test)
{
std::cout<<d<<" ";
}
std::cout<<std::endl;
for(double d : test)
{
std::cout<<exp(d)<<" ";
}
std::cout<<std::endl;
}
Output:
0 0.295395 0.523137 0.708513 0.86484 1
1 1.34366 1.68731 2.03097 2.37463 2.71828
At the moment this function only produces ascending lists (it just assumes that the smaller value is the left bound). There are several ways to make it work for descending lists as well (always assuming the leftmost argument to be the left bound). I just wanted to make the function as simple as possible and I think if you understand the function it will be easy for you to add that functionality.
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