How to capture a string into variable in a recursive function? - c++

I tried to print all the possible combination of members of several vectors. Why
the function below doesn't return the string as I expected?
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
using namespace std;
string EnumAll(const vector<vector<string> > &allVecs, size_t vecIndex, string
strSoFar)
{
string ResultString;
if (vecIndex >= allVecs.size())
{
//cout << strSoFar << endl;
ResultString = strSoFar;
//return ResultString;
}
for (size_t i=0; i<allVecs[vecIndex].size(); i++) {
strSoFar=EnumAll(allVecs, vecIndex+1, strSoFar+allVecs[vecIndex][i]);
}
ResultString = strSoFar; // Updated but still doesn't return the string.
return ResultString;
}
int main ( int arg_count, char *arg_vec[] ) {
vector <string> Vec1;
Vec1.push_back("T");
Vec1.push_back("C");
Vec1.push_back("A");
vector <string> Vec2;
Vec2.push_back("C");
Vec2.push_back("G");
Vec2.push_back("A");
vector <string> Vec3;
Vec3.push_back("C");
Vec3.push_back("G");
Vec3.push_back("T");
vector <vector<string> > allVecs;
allVecs.push_back(Vec1);
allVecs.push_back(Vec2);
allVecs.push_back(Vec3);
string OutputString = EnumAll(allVecs,0,"");
// print the string or process it with other function.
cout << OutputString << endl; // This prints nothing why?
return 0;
}
The expected output is:
TCC
TCG
TCT
TGC
TGG
TGT
TAC
TAG
TAT
CCC
CCG
CCT
CGC
CGG
CGT
CAC
CAG
CAT
ACC
ACG
ACT
AGC
AGG
AGT
AAC
AAG
AAT

You call EnumAll recursively, but you ignore the string that it returns. You have to decide how you are going to aggregate those strings - or what you are going to do with them.

Your function doesn't return anything because your last call doesn't return anything since there's no return and the end of your function.
Edit:
One thing that you can do, is to insert your ResultString to a global vector each time before the return. And at the end, all your results will be available in this vector.

Here is an alternate solution. This does not expect you to pass anything but the initial vectors:
int resultSize( vector< vector<string> > vector ){
int x=1;
for( int i=0;i<vector.size(); i++ )
x *= vector[i].size();
return x;
}
vector<string> enumAll(const vector< vector<string> > allVecs )
{
//__ASSERT( allVecs.size() > 0 );
vector<string> result;
if( allVecs.size() == 1 ){
for( int i=0 ; i< allVecs[0].size(); i++){
result.push_back( allVecs[0][i] );
}
return result;
}
for( int i=0; i<allVecs[0].size(); i++ ){
for( int j=0; j<resultSize( vector< vector<string> >(allVecs.begin()+1, allVecs.end() ) ); j++){
result.push_back( allVecs[0][i] + enumAll(vector< vector<string> >(allVecs.begin()+1, allVecs.end() ))[j] );//enumAll on each tempVector is called multiple times. Can be optimzed.
}
}
}
Advantage of this method:
This is very readable in terms of the recursion. It has easily identifiable recursion base step and also the recursion itself. It works as follows: Each iteration of the recursion enumerates all possible strings from n-1 vectors and the current step simply enumerates them.
Disadvantages of this method:
1. enumAll() function is called multiple times returning the same result.
2. Heavy on stack usage since this is not tail recursion.
We can fix (1.) by doing the following, but unless we eliminate tail recursion, we cannot get rid of (2.).
vector<string> enumAll(const vector< vector<string> > allVecs )
{
//__ASSERT( allVecs.size() > 0 );
vector<string> result;
if( allVecs.size() == 1 ){
for( int i=0 ; i< allVecs[0].size(); i++){
result.push_back( allVecs[0][i] );
}
return result;
}
const vector< vector<string> > tempVector(allVecs.begin()+1, allVecs.end() );
vector<string> tempResult = enumAll( tempVector );// recurse
int size = resultSize( tempVector );
cout << size << " " << tempResult.size() << endl;
for( int i=0; i<allVecs[0].size(); i++ ){
for( int j=0; j<size; j++){
result.push_back( allVecs[0][i] + tempResult[j] );
}
}
}

Your second return should also accumulate the strSoFar in some way. Something like:
for (size_t i=0; i<allVecs[vecIndex].size(); i++)
{
strSoFar = EnumAll(allVecs, vecIndex+1, strSoFar+allVecs[vecIndex][i]);
}
ResultString = strSoFar;
return ResultString;

The code you provided crashes. In the following line, notice that you will be exceeding the limits of vecIndex. There is no check on it in the loop. Also, in the if condition above, you donot reset the vecIndex either. So you will have an access violation.
strSoFar = EnumAll(allVecs, vecIndex+1, strSoFar+allVecs[vecIndex][i]);
To fix it, either rest vecIndex in the if() or use the following for statement:
for (size_t i=0; i<allVecs[vecIndex].size() && vecIndex < allVecs.size(); i++){...}
Edit: However, this does not give the correct output yet.

Your function determines all the correct combinations but they are lost since you do not aggregate them properly.
I see you asked the same question here. I will assume you are now looking for a means to get the output back to the top level so you can handle it from there.
The problem then comes down to how you aggregate the output. You are using a string, but are looking for multiple rows of data. There are infinite answers to this .. here is one using a vector container.
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
using namespace std;
void printAll(const vector<string> data);
void EnumAll(const vector<vector<string> > &allVecs, size_t vecIndex, vector<string>&allStr, string strSoFar)
{
if (vecIndex >= allVecs.size())
{
allStr.push_back(strSoFar);
return;
}
for (size_t i=0; i<allVecs[vecIndex].size(); i++)
EnumAll(allVecs, vecIndex+1, allStr, strSoFar+allVecs[vecIndex][i]);
}
int main ( int arg_count, char *arg_vec[] ) {
vector <string> Vec1;
Vec1.push_back("T");
Vec1.push_back("C");
Vec1.push_back("A");
vector <string> Vec2;
Vec2.push_back("C");
Vec2.push_back("G");
Vec2.push_back("A");
vector <string> Vec3;
Vec3.push_back("C");
Vec3.push_back("G");
Vec3.push_back("T");
vector <vector<string> > allVecs;
allVecs.push_back(Vec1);
allVecs.push_back(Vec2);
allVecs.push_back(Vec3);
vector<string> allStr;
EnumAll(allVecs,0,allStr,"");
// print the string or process it with other function.
printAll(allStr);
return 0;
}
void printAll(const vector<string> data)
{
vector<string>::const_iterator c = data.begin();
while(c!=data.end())
{
cout << *c << endl;
++c;
}
}

Related

Segmentation Fault Passing Reference as Function Parameter

With this block of code, I'm getting a segmentation fault as I try to pass the stack references to the transferStacks() method. Any help on understanding why this is would be helpful!
I could just get rid of the helper method and it should work, but I'm trying to understand conceptually.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <stack>
using namespace std;
void transferStacks(stack<int> & s1, stack<int> & s2){
if (s1.empty()){
for (int i = 0; i < s2.size(); i++){
int element = s2.top();
s1.push(element);
s2.pop();
}
}
}
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int queries = 0;
cin>>queries;
stack <int> newestOnTop;
stack <int> oldestOnTop;
while (queries!=0){
int type = 0;
cin >> type;
int input = 0;
if (type == 1){ //enqueue
cin>>input;
newestOnTop.push(input);
}
else if (type == 2){ //dequeue
transferStacks(newestOnTop, oldestOnTop);
oldestOnTop.pop();
}
else if (type == 3){ //peek
transferStacks(newestOnTop, oldestOnTop);
cout<<oldestOnTop.top()<<endl;
}
queries--;
}
return 0;
}
Segmentation Fault
You appear to believe that this code will copy s2 to s1:
for (int i = 0; i < s2.size(); i++){
int element = s2.top();
s1.push(element);
s2.pop();
}
But it will not: if before the loop s2 contains 3 elements, only the first 2 will be copied (and generally, only the first half will be copied).
In addition, your transfer function transfers from s2 to s1, but the way you call it implies that you intended the opposite: to transfer from s1 to s2. Current code would leave oldestOnTop empty, which will then result in a crash when you use oldestOnTop.top() or oldestOnTop.pop().

Error when calling void function with <set> operator

I am trying to pass a string and and an empty set into my function. Then I would like to call the function in my main and print all of the elements in the set.
This is my function code:
#include<iostream>
using std::cout; using std::endl;
#include<algorithm>
using std::set_union; using std::copy;
#include<iterator>
using std::inserter; using std::ostream_iterator;
#include<string>
using std::string;
#include<set>
using std::set;
void removing(const string &word, set<string> &result) {
string del_word = word;
char erased_l;
for(int i = 0; i < del_word.length(); i++) {
erased_l = word[i];
del_word.erase(0, 1);
del_word = erased_l + del_word;
}
}
Below is my main code where I call the function:
int main (){
set<string> jump = {};
set<string> del = removing("axiom", jump);
for (string ele:del) {
cout << ele << endl;
}
}
I get the following error:
No viable conversion from 'void' to 'set<std::__1::string>' (aka 'set<basic_string<char, char_traits<char>, allocator<char> > >')
The error is in line 16:
set<string> del = removing("axiom", jump);
My code is trying to accomplish:
If I pass in axiom, then I would like my string set to have {xiom, aiom, axom, axim, axio}. So remove first letter, keep rest of the word. Then remove second letter, keep rest of the word, etc...
Primary issues include:
The return value of a void function can't be assigned to a set, hence your compiler error. Your design is to pass a reference to an empty result set into the removing function and have it populated with the result data, so you can remove the assignment here.
Nothing is added to your result inside your removing function, so it starts empty and ends empty after the function call.
Here's a working version:
void removing(const string &word, set<string> &result) {
for (int i = 0; i < word.length(); i++) {
result.insert(word.substr(0, i) + word.substr(i + 1, word.length()));
}
}
int main () {
set<string> jump = {};
removing("axiom", jump);
for (string ele : jump) {
cout << ele << endl;
}
}
Output:
aiom
axim
axio
axom
xiom
Having said that, it's not clear to me why result should be a parameter to the function. If you're only planning on using it to store this particular result, this design seems much cleaner from the perspective of the caller:
set<string> removing(const string &word) {
set<string> result;
for (int i = 0; i < word.length(); i++) {
result.insert(word.substr(0, i) + word.substr(i + 1, word.length()));
}
return result;
}
int main () {
set<string> jump = removing("axiom");
for (string ele : jump) {
cout << ele << endl;
}
}
Try it!

Find char* element in array of char* in C++

I'm trying to write function that search for char * element in array of char* and the function start check this element, if the element exist in the array I will have "found", if not it should be "inserted" and the element added to the array.
I wrote this code but I cannot know how to try it, the program always gives me exception, what can I do to check the element in my pointer array?
void checkFunction(char*myArray[], char *element,bool flag)
{
for (int i = 0; i < strlen(*myArray) ; ++i)
{
if (myArray[i] == element)
{
flag = true;
}
}
*myArray = element;
flag = false;
if (flag)
{
cout << "Found" << endl;
}
else
{
cout << "Inserted" << endl;
}
}
C++ Way
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(int argc, const char * argv[]) {
vector<string> myStrings { "One", "Two", "Three" };
// std::find() finds the first element that matches a value
auto it = find(begin(myStrings), end(myStrings), "Twooo");
if (it != end(myStrings)) {
cout << "We found this string; do something..." << endl;
}
}
Few remarks regarding your function:
1.Why do you need the third parameter bool flag, instead of having it as local variable?
2.If you want to expand an array you should copy the old to a newly allocated and then add the new element, you can not just do: *myArray = element;
3.If you want to iterate through the array length/ size, instead of:
for (int i = 0; i < strlen(*myArray) ; ++i)
pass an additional parameter to your function, that indicates the number of elements in the array.
With std::string and std::vector you could do something like:
void check_insert (std::vector<std::string>& v, std::string& c) {
for (auto i = 0; i < v.size(); ++i) {
if (v[i] == c) {
std::cout << "Found!\n";
return;
}
}
v.push_back(c);
std::cout << "Inserted!\n";
}

Palindrome Partitioning (how to figure out how to use DFS)

My general question is how to figure out how to use DFS. It seems to be a weak part of my knowledge. I have vague idea but often get stuck when the problem changes. It caused a lot of confusion for me.
For this question, I got stuck with how to write DFS with recursion.
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
For example, given s = "aab",
Return
[
["aa","b"],
["a","a","b"]
]
My first attempt was stuck in the loop of the helper function. Then from searching on internet, I found that bool palindrome(string s) can be written as a different signature.
bool palindrome(string &s, int start, int end)
This leads to the correct solution.
Here's the code of my initial attempt:
class Solution {
public:
bool palindrome(string s)
{
int len = s.size();
for (int i=0;i<len/2; i++)
{
if (s[i]!=s[len-i])
return false;
}
return true;
}
void helper( int i, string s, vector<string> &p, vector<vector<string>> &ret)
{
int slen = s.size();
if (i==slen-1&&flag)
{
ret.push_back(p);
}
for (int k=i; k<slen; k++)
{
if (palindrome(s.substr(0,k)))
{
p.push_back(s.substr(0,k)); //Got stuck
}
}
i++;
}
vector<vector<string>> partition(string s) {
vector<vector<string>> ret;
int len=s.size();
if (len==0) return ret;
vector<string> p;
helper(0,s,p,ret);
return ret;
}
};
Correct one:
class Solution {
public:
bool palindrome(string &s, int start, int end)
{
while(start<end)
{
if (s[start]!=s[end])
return false;
start++;
end--;
}
return true;
}
void helper( int start, string &s, vector<string> &p, vector<vector<string>> &ret)
{
int slen = s.size();
if (start==slen)
{
ret.push_back(p);
return;
}
for (int i=start; i<s.size(); i++)
{
if (palindrome(s, start, i))
{
p.push_back(s.substr(start,i-start+1));
helper(i+1,s,p,ret);
p.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
vector<vector<string>> ret;
int len=s.size();
if (len==0) return ret;
vector<string> p;
helper(0,s,p,ret);
return ret;
}
};
Edit Dec. 4, 2014: I saw some approach using dynamical programming but can't understand the code completely.
esp. isPalin[i][j] = (s[i] == s[j]) && ((j - i < 2) || isPalin[i+1][j-1]);
Why j-I<2 instead of j-I<1?
class Solution {
public:
vector<vector<string>> partition(string s) {
int len = s.size();
vector<vector<string>> subPalins[len+1];
subPalins[0] = vector<vector<string>>();
subPalins[0].push_back(vector<string>());
bool isPalin[len][len];
for (int i=len-1; i>=0; i--)
{
for (int j=i; j<len; j++)
{
isPalin[i][j] = (s[i]==s[j])&&((j-i<2)||isPalin[i+1][j-1]);
}
}
for (int i=1; i<=len;i++)
{
subPalins[i]=vector<vector<string>>();
for (int j=0; j<i; j++)
{
string rightStr=s.substr(j,i-j);
if (isPalin[j][i-1])
{
vector<vector<string>> prepar=subPalins[j];
for (int t=0; t<prepar.size(); t++)
{
prepar[t].push_back(rightStr);
subPalins[i].push_back(prepar[t]);
}
}
}
}
return subPalins[len];
}
};
What exactly are you asking? You have correct working code and your non-working code which is not that different.
I guess I can point out several issues with your code - may be it will be helpful to you:
in the palindrome() function you should compare s[i] to s[len-1-i] rather than to just s[len-i] in the if, since in former case you will compare 1st element (having index 0) to the non-existent element (index len). That might be the reason helper() got stuck.
in the helper() function flag is not initialized. In the for cycle, the end condition should be k<slen-1 instead of k<slen, since in latter case you will omit checking the substring that includes the terminal symbol of the string. Also, incrementing i in the end of helper() is pointless. Finally, indentations are messy in the helper() function.
Not sure why you use DFS - what is the meaning of your graph, what are the vertices and edges here? As to how the recursion works here: in the helper() function you start checking substrings of increased length for being palindrome. If the palindrome is found, you place it into p vector (which represent your current partitioning) and try to break the remainder of the string into palindromes by calling helper() recursively. If you succeed in that (i.e. if the whole string is completely partitioned into palindromes) you place the contents of p vector (current partitioning) into ret (set of all found partitionings), and then clear p to prepare it for the analysis of the next partition (purge of p is achieved by pop_back() call that follows recursive call of helper()). If, on the other hand, you fail to completely break string into palindromes, the p is purged as well, but without transferring its content into ret (this is due to the fact that recursive call for the last piece of string - which is not a palindrome - returns without calling helper() for the final symbol and thus pushing p into ret does not occur). Therefore you end up having all possible palindrome partitionings in the ret.
Hi~ this is my code using DFS + backtracking.
class Solution
{
public:
bool isPalindrome (string s) {
int i = 0, j = s.length() - 1;
while(i <= j && s[i] == s[j]) {
i++;
j--;
}
return (j < i);
}
void my_partition(string s, vector<vector<string> > &final_result, vector<string> &every_result ) {
if (s.length() ==0)
final_result.push_back(every_result);
for (int i =1; i <= s.length();++i) {
string left = s.substr(0,i);
string right = s.substr(i);
if (isPalindrome(left)) {
every_result.push_back(left);
my_partition(right, final_result, every_result);
every_result.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
vector<vector<string> > final_result;
vector<string> every_result;
my_partition(s, final_result, every_result);
return final_result;
}
};
I have done Palindrome Partitioning using backtracking. Depth-first search was used here, idea is to split the given string so that the prefix is a palindrome. push prefix in a vector now explore the string leaving that prefix and then finally pop the last inserted element,
Well on spending time on backtracking is of the form, choose the element, explore without it and unchoose it.
enter code here
#include<iostream>
#include<vector>
#include<string>
using namespace std;
bool ispalidrome(string x ,int start ,int end){
while(end>=start){
if(x[end]!=x[start]){
return false;
}
start++;
end--;
}
return true;
}
void sub_palidrome(string A,int size,int start,vector<string>&small, vector < vector < string > >&big ){
if(start==size){
big.push_back(small);
return;
}
for(int i=start;i<size;i++){
if( ispalidrome(A,start,i) ){
small.push_back(A.substr(start,i-start+1));
sub_palidrome(A,size,i+1,small,big);
small.pop_back();
}
}
}
vector<vector<string> > partition(string A) {
int size=A.length();
int start=0;
vector <string>small;
vector < vector < string > >big;
sub_palidrome(A,size,start,small,big);
return big;
}
int main(){
vector<vector<string> > sol= partition("aab");
for(int i=0;i<sol.size();i++){
for(int j=0;j<sol[i].size();j++){
cout<<sol[i][j]<<" ";
}
cout<<endl;
}
}

Sorting of vector containing structure

I was trying to sort a vector of struct.The following is my code.I am not able to sort it properly...Can anyone help me..?I need to sort according to the mmNo.Sorry ...i missed some part of the code...
typedef struct MMInfo
{
std :: string strMmNo;
std :: string strMmName;
std :: string strMmsPlace;
std :: string strMmAdd;
std :: string strMmPh;
MMInfo(const std::string& mmNo,
const std::string& mmName,
const std::string& mmPlace,
const std::string& mmAdd,
const std::string& mmPh) : stringValue(mmNo,),stringValue(mmName),
stringValue(mmPlace),stringValue(mmAdd),
stringValue(mmPh) {}
bool operator < (const MMInfo& str) const
{
return (mmNo < str.mmNo);
}
} MMInfo;
std::vector < MMInfo > mmlist;
MMInfo mmInfo = {"", "", "", "", ""};
mmInfo.strMmNo = "3452132"; //actually , i have used a loop to get it from the user
mmInfo.strMmName="Peter";
mmInfo.strMmPlace="TCR";
mmInfo.strMmAdd="Street 453";
mmInfo.strMmPh="8587556587";
mmlist.push_back(mmInfo);
sort(mmlist.begin(),mmlist.end());
for (int i=0; i<mmlist.size(); i++)
{
cout << " first row :" << mmlist[i].strMmNo << " " << mmlist[i].strMmName
<<" " <<mmlist[i].strMmsPlace << " " << mmlist[i].strMmsAdd ;
}
Your code has no problems. I mean, the usage is right but the structure definition seems not correct. It's not compilable at least in Visual C++ 9.0 Please make a proper initialization list. The following code worked fine for me
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct NodeInfo
{
int x;
NodeInfo( int xi ){ x = xi; }
bool operator < (const NodeInfo& str) const
{
return (x < str.x);
}
}MMInfo;
int _tmain(int argc, _TCHAR* argv[])
{
std::vector < MMInfo > mmlist;
mmlist.push_back( 1 );
mmlist.push_back( 31 );
mmlist.push_back( 21 );
mmlist.push_back( 11 );
mmlist.push_back( 41 );
sort(mmlist.begin(),mmlist.end());
for (unsigned int i=0; i<mmlist.size(); i++)
{
cout<< " x row : \n" << mmlist[i].x ;
}
return 0;
}
Does that even compile? (No!)
You're trying to initialize values that don't exist. Maybe initialize your strMm* values instead of stringValue?
You're initializing the same value (that doesn't even exist!) multiple times (Initialize strMm* members with a corresponding mm* value)
Your comparison function compares values that don't exist. (Compare strMmNo < str.strMmNo).
Also, you don't even have values to sort in your list.