I'm trying to learn memoization in C++ and have implemented two Fibonacci functions using map and vector. I've submitted them to the Coursera data structures course. The vector implementation fails due to taking too much time and the map passes OK. As both implement memoization could anybody suggest why one fails and the other passes?
#include <iostream>
#include <map>
#include <iterator>
#include <vector>
using namespace std;
int fibonacci_fast_vector(int n)
{
vector <int> cache;
if(n<=1) {
return n;
}
else if ((unsigned)n >= cache.size()) {
cache.resize(n+1);
}
if(cache[n] != 0) {
return cache[n];
}
// otherwise
int ret=fibonacci_fast_vector(n-1)+fibonacci_fast_vector(n-2);
cache[n]=ret;
return ret;
}
int fibonacci_fast_map(int n)
{
static map<int,int>memo;
if(n<=1)
return n;
if(memo.count(n)>0) { /*if it is in the map return the element*/
return memo[n];
}
// otherwise
int ret=fibonacci_fast_map(n-1)+fibonacci_fast_map(n-2);
memo[n]=ret;
return ret;
}
int main() {
int n = 0;
std::cin >> n;
std::cout << fibonacci_fast_map(n) << '\n';
std::cout << fibonacci_fast_vector(n) << '\n';
return 0;
}
In this code:
int fibonacci_fast_vector(int n)
{
vector <int> cache;
your vector is not static so you create a new vector on every function call, so your "memoization" not only fails to work but actually makes it slower.
Btw this code:
if(memo.count(n)>0) { /*if it is in the map return the element*/
return memo[n];
}
is unnecessary inefficient - you are doing 2 lookups in case data is there or 2 lookups if it is not, which is significantly expensive operation on a map. You should use something like this:
auto p = memo.emplace(n,0);
if( p.second ) // data was not there
p.first->second = fibonacci_fast_map(n-1)+fibonacci_fast_map(n-2);
return p.first->second;
I guess the problem is that your vector is not static. Put a static keyword or declare it in the global scope. This will reduce the huge performance time because you avoid many news and deletes. Also you can create with some initial size vector if you know the probable size for the same performance reason.
Related
I am working on a project where I parse a string in to an array and then return it back to the main function. It parses fine but when I return it to the main function I can't get access to the array elements.
//This is from the Main function. It calls commaSeparatedToArray which returns the array.
for (int i = 0; i < numberOfStudents; i++) {
string * parsedToArray = mainRoster->commaSeparatedToArray(studentData[i]);
Degree degreeType = SOFTWARE;
for (int i = 0; i < 3; i++) {
if (degreeTypeStrings[i] == parsedToArray[8])
degreeType = static_cast<Degree>(i);
}
mainRoster->add(parsedToArray[0], parsedToArray[1], parsedToArray[2], parsedToArray[3], stoi(parsedToArray[4]), stoi(parsedToArray[5]), stoi(parsedToArray[6]), stoi(parsedToArray[7]), degreeType);
}
//Here is the commaSeparatedToArray function
string * roster::commaSeparatedToArray(string rowToParse) {
int currentArraySize = 0;
const int expectedArraySize = 9;
string valueArray[expectedArraySize];
int commaIndex = 0;
string remainingString = rowToParse;
while (remainingString.find(",") != string::npos) {
currentArraySize++;
if (currentArraySize <= expectedArraySize) {
commaIndex = static_cast<int>(remainingString.find(","));
valueArray[currentArraySize - 1] = remainingString.substr(0, commaIndex);
remainingString = remainingString.substr(commaIndex + 1, remainingString.length());
}
else {
cerr << "INVALID RECORD. Record has more values then is allowed.\n";
exit(-1);
}
}
if (currentArraySize <= expectedArraySize) {
currentArraySize++;
commaIndex = static_cast<int>(remainingString.find(","));
valueArray[currentArraySize - 1] = remainingString.substr(0, commaIndex);
remainingString = remainingString.substr(commaIndex + 1, remainingString.length());
}
if (currentArraySize < valueArray->size()) {
cerr << "INVALID RECORD. Record has fewer values then is allowed.\n";
exit(-1);
}
return valueArray;
}
1) You can't return arrays in C++. Your code (as I'm sure you know) returns a pointer to an array. That's an important difference.
2) The array is declared locally in the function and therefore no longer exists after the function has exitted.
3) Therefore once you have returned from the function you have a pointer to something which no longer exists. Bad news.
4) You must always consider the lifetime of objects when you program C++. One solution to this problem is to dynamically allocate the array (using new[]). This means that the array will still exist when you exit the function. But it has the signifcant disavantage that you must remember to delete[] the array at a suitable later time.
5) The best solution (in general) is to use a std::vector. Unlike an array a std::vector can be returned from a function. So this option leads to the simplest, most natural code.
vector<string> roster::commaSeparatedToArray(string rowToParse) {
...
vector<string> valueArray(expectedArraySize);
...
return valueArray;
}
Since your array/vector is constant size, you could also use a std::array
array<string, expectedArraySize> valueArray;
To complete the answer that John has already given, I made some example code to show you, how such function could look like.
Parsing, or tokenizing can be easily done with the std::sregex_token_iterator. That is one of the purposes for this iterator. You can see the simplicity of the usage below.
In the function we define a vector af string and use its range constructor to do the whole tokenizing.
Then we make a sanity check and return the data.
Please see:
#include <string>
#include <regex>
#include <iterator>
#include <vector>
#include <algorithm>
#include <iostream>
const std::regex separator(",");
constexpr size_t ExpectedColumnSize = 9;
std::vector<std::string> commaSeparatedToArray(std::string rowToParse)
{
// Parse row into substrings
std::vector<std::string> columns{
std::sregex_token_iterator(rowToParse.begin(),rowToParse.end(),separator ,-1),
std::sregex_token_iterator() };
// Check number of columns
if (columns.size() != ExpectedColumnSize) {
std::cerr << "Error. Unexpected number of columns in record\n";
}
return columns;
}
// test code
int main()
{
// Define test data
std::string testInputData{ "1,2,3,4,5,6,7,8,9" };
// Get the result from the parser
std::vector<std::string> parsedElements{ commaSeparatedToArray(testInputData) };
// show the result on the console
std::copy(parsedElements.begin(), parsedElements.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
I am using this code below which returns the smallest positive integer in a vector. I got the code here. My question is there a reason to pass the size to the function, can you not calculate it in the function body?
Also what is the second if() testing for? I can't understand how this if statement works?
#include <vector>
using namespace std;
int rec_min_pos(const vector<int> & nums, int size) {
if (size < 1) {
return INT_MAX;
}
if(nums[size-1] > 0){
return min(nums[size-1], rec_min_pos(nums, size-1));
}
else{
return rec_min_pos(nums, size-1);
}
}
The second if statement checks for positivity of the element, since the function shall return the minimum positive integer.
Your function is recursive and the 'size' argument is actually one plus the index to the last element to be tested. This allows a simple recursive function design, but requires an additional argument. It's presumably better to make these points explicit in the function interface
inline int recursive_min_positive(const int*arr, size_t i)
{
return
i==0? std::numeric_limits<int>::max() :
arr[i-1]<=0? recursive_min_positive(arr,i-1) :
std::min(arr[i-1],recursive_min_positive(arr,i-1) ;
}
int min_positive(std::vector<int> const&arr)
{
return recursive_min_positive(arr.data(), arr.size());
}
Recursive function design is often elegant, but inefficient (though compilers tend to unroll the recursion). Here, a non-recursive implementation is actually shorter and clearer.
int min_positive(std::vector<int> const&arr)
{
int result = std::numeric_limits<int>::max();
for(auto val : arr)
if(0 < val && val < result) result = val;
return result;
}
In addition to all comments: you can overload the function like this:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Original function with size argument
int rec_min_pos(const vector<int> & nums, int size) {
if (size < 1) {
return INT_MAX;
}
if (nums[size - 1] > 0) {
return min(nums[size - 1], rec_min_pos(nums, size - 1));
}
else {
return rec_min_pos(nums, size - 1);
}
}
// Overloaded rec_min_pos function
int rec_min_pos(const vector<int> & nums) {
// here we just call the original rec_mon_pos function
return rec_min_pos(nums, nums.size());
}
int main()
{
vector<int> v{ 9,2,7,3,7,5,6 };
cout << rec_min_pos(v); // call the overloaded function
}
Output:
2
Not related to the recursive function, but expanding on my comment:
int min_positive(std::vector<int> & nums)
{
auto elem = std::min_element(nums.begin(), nums.end(),
[](int lhs, int rhs){ return std::tie(std::signbit(lhs), lhs) < std::tie(std::signbit(rhs), rhs); }
);
if ((elem == nums.end()) || std::signbit(*elems)) { return MAX_INT; }
return *elem;
}
Here we define a comparison function that orders positive before negative, and then by value. We use the three argument std::min_element, which will find us an iterator in nums.
The first check handles an empty nums, and the second one where every value is negative, both of which the original ignores, returning MAX_INT
Here is my code. I'm getting a run time error. Is there a better way to procede recursively?
The goal is: taking 3 as the input will result this
1 1 1
2 1
3
If there is a better way to implement easy recursion, i'm listening
#include <iostream>
using namespace std;
int divide(int input,int memory) {
if(memory==input){
cout<<input;
exit(1);
}
cout<<memory<<" ";
int i=memory;
for(i;i<input;i++){
cout<<1<<" ";
}
cout<<endl;
memory++;
divide(input,memory);
}
int main() {
// your code goes here
divide(8,1);
return 0;
}
You simply get a runtime error because of this line:
exit(1);
Change it to:
exit(0);
Btw, if you just want to stop the function when input==memory instead use:
return 0;
EDIT: int divide(int input,int memory) { this means you must return an int. If you don't really need to return anything, change it to:
void divide(int input,int memory) {
and use: return; to stop the recursion
EDIT: Since you asked a cleaner implementation (in my opinion) would be:
void divide(int input,int memory) {
std::vector<int> result(input - memory + 1, 1);
result.front() = memory;
std::copy(result.begin(), result.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << endl;
if (input < ++memory) return;
divide(input,memory);
}
I am trying to do a foreach on a vector of attacks, each attack has a unique ID say, 1-3.
The class method takes the keyboard input of 1-3.
I am trying to use a foreach to run through my elements in m_attack to see if the number matches, if it does... do something.
The problem I'm seeing is this:
a'for each' statement cannot operate on an expression of type "std::vector<Attack
Am I going about this totally wrong, I have C# experience and is kind of what I'm basing this on, any help would be appreciated.
My code is as follows:
In header
vector<Attack> m_attack;
In class
int Player::useAttack (int input)
{
for each (Attack* attack in m_attack) // Problem part
{
//Psuedo for following action
if (attack->m_num == input)
{
//For the found attack, do it's damage
attack->makeDamage();
}
}
}
For next examples assumed that you use C++11.
Example with ranged-based for loops:
for (auto &attack : m_attack) // access by reference to avoid copying
{
if (attack.m_num == input)
{
attack.makeDamage();
}
}
You should use const auto &attack depending on the behavior of makeDamage().
You can use std::for_each from standard library + lambdas:
std::for_each(m_attack.begin(), m_attack.end(),
[](Attack * attack)
{
if (attack->m_num == input)
{
attack->makeDamage();
}
}
);
If you are uncomfortable using std::for_each, you can loop over m_attack using iterators:
for (auto attack = m_attack.begin(); attack != m_attack.end(); ++attack)
{
if (attack->m_num == input)
{
attack->makeDamage();
}
}
Use m_attack.cbegin() and m_attack.cend() to get const iterators.
This is how it would be done in a loop in C++(11):
for (const auto& attack : m_attack)
{
if (attack->m_num == input)
{
attack->makeDamage();
}
}
There is no for each in C++. Another option is to use std::for_each with a suitable functor (this could be anything that can be called with an Attack* as argument).
The for each syntax is supported as an extension to native c++ in Visual Studio.
The example provided in msdn
#include <vector>
#include <iostream>
using namespace std;
int main()
{
int total = 0;
vector<int> v(6);
v[0] = 10; v[1] = 20; v[2] = 30;
v[3] = 40; v[4] = 50; v[5] = 60;
for each(int i in v) {
total += i;
}
cout << total << endl;
}
(works in VS2013) is not portable/cross platform but gives you an idea of how to use for each.
The standard alternatives (provided in the rest of the answers) apply everywhere. And it would be best to use those.
C++ does not have the for_each loop feature in its syntax. You have to use c++11 or use the template function std::for_each.
struct Function {
int input;
Function(int input): input(input) {}
void operator()(Attack& attack) {
if(attack->m_num == input) attack->makeDamage();
}
};
Function f(input);
std::for_each(m_attack.begin(), m_attack.end(), f);
I'm trying to count the number of calls within a recursive permutation function.
I've written a function that fills a queue with all the permutations but I can't seem to figure out how to maintain an accurate count.
Ultimately i'd like the function to return a subset of the permuatations specified by lbound and ubound arguments, and to do so I think i need someway to keep an internal count.
Using the size of the returned queue will not work since i'd like the function to be able to handle permutations too big to hold in memory.
For this code i'd like the count to be returned as 100.
#include <vector>
#include <iostream>;
using namespace std;
int& Permutations(vector<vector<int>> param, vector<vector<int>> &perm, int index=0)
{
static vector<int> iter;
static int count = 0;
if (index == param.size())
{
perm.push_back(iter); // add permutation to queue
count++;
return count;
}
for (int i=param[index][0]; i<=param[index][1]; i+=param[index][2])
{
if (iter.size() > index) iter[index] = i;
else iter.push_back(i);
Permutations(param, perm, index+1); // recursive function
}
}
void main()
{
vector<vector<int>> params; // vector of parameter vectors
vector<int> param1, param2;
int arr1[3] = {0,9,1}; // range for each parameter vector
int arr2[3] = {0,9,1}; // specified as lbound, ubound, step
param1.insert(param1.end(),arr1,arr1+3);
param2.insert(param2.end(),arr2,arr2+3);
params.push_back(param1);
params.push_back(param2);
vector<vector<int>> queue; // queue of generated permutations
int permcount = Permutations(params,queue);
cout << "the permutation count is " << permcount << endl;
cin.get();
}
Using a static count will not work, because it's not going to ever be reset (and will cause problems if you ever go multi-threaded).
Instead, how about this:
int Permutation(/* params */)
{
int count = 1; // Count ourself
for (whatever)
{
count += Permutation(whatever); // Count cumulative sum from recursion
}
return count;
}
Each call to Permutation() returns the total number of calls that were made below it in the call tree. As we unwind, all the counts from the sub-trees get summed together, to eventually produce the final return value.
int foo(int count,/*Other Params*/) {
/*Calucation*/
if (!terminatingCondition) {
foo(count++,/*Other Params*/);
}
logger.log("foo was called " + count + "times");
return /*calcualtion*/;
}
I'm just trying to answer the question by ignoring your actual algorithm purpose. The two statics should be moved to argument references, or you don't have a good way to reset their values.
void Permutations(vector<vector<int>> param, vector<vector<int>> &perm, vector<int> &iter, int &count, int index=0)
{
++count;
// ...
}