String permutation recursion issue - c++

(--This question was answered down below--)
Hey guys so I know this question has been answered in various ways so far on this site but I wanted to see if I could get a hint to my question without getting the blunt answer... sorry if this is redundant!
so... so far my code is this (as the function says, this is supposed to print out every permutation of the string "ABCD" and MUST be done recursively and without the use of STL algorithms):
void printPermutations(string prefix, string remainder)
{
if (remainder.empty())
cout<<prefix<<endl;
else {
for(int i = 0; i<remainder.length(); i++)
{
prefix += remainder[i];
remainder = (remainder.substr(0, i) + remainder.substr(i+1)); //Gets rid of selected char
printPermutations(prefix, remainder); //recursion w/updated values. Problem here?
}
}
}
Where remainder = "ABCD" as a test string. I'm assuming my problem is with the recursive call itself?
So far, the function only prints out the first 3 permutations: ABCD, ABDC, ACBD. I also have a hunch that this could have something to do with the for control since it printed out 3 permutations and 3 would be less than the string's length of 4? I don't know. I just started learning recursion and it's really hard for me to figure out how to implement recursive calls properly.

The problem is that you're modifying both strings in the loop, so prefix grows and remainder shrinks.
That is, you want the "top-level" call to iterate through A/BCD, B/ACD, C/ABD, and D/ABC, but you're iterating through A/BCD, AB/CD, ABC/D, and ABCD/empty.
Don't modify the strings, just pass the values you want to the recursion:
void printPermutations(string prefix, string remainder)
{
if (remainder.empty())
cout<<prefix<<endl;
else {
for(int i = 0; i<remainder.length(); i++)
{
printPermutations(prefix + remainder[i],
remainder.substr(0, i) + remainder.substr(i+1));
}
}
}
Or use "fresh" variables if you want a more "step-by-step" look:
void printPermutations(string prefix, string remainder)
{
if (remainder.empty())
cout<<prefix<<endl;
else {
for(int i = 0; i<remainder.length(); i++)
{
string thisPrefix = prefix + remainder[i];
string thisRemainder = remainder.substr(0, i) + remainder.substr(i+1);
printPermutations(thisPrefix, thisRemainder);
}
}
}

Please consider using the stl algorithm next_permutation for the job. The code in your case is than:
#include <algorithm>
#include <string>
#include <iostream>
int main()
{
std::string s = "ABCD";
std::sort(s.begin(), s.end());
do {
std::cout << s << '\n';
} while(std::next_permutation(s.begin(), s.end()));
}
If you need to, you can write a wrapper around this snippet.

Related

function returns an empty vector

I am trying to return a vector of strings from a function, but every time I do so I get an empty vector.However when I try to print the vector in the function itself it's not empty but when I try to print the returned vector I am getting nothing printed.
#include <iostream>
#include <vector>
using namespace std;
vector<string> permute(string S, string chosen){
vector<string> permutated_strings;
if(S.empty())
permutated_strings.push_back(chosen);
else{
for(int i=0;i<S.length();i++){
char c = S[i];
chosen += c;
S.erase(i,1);
permute(S,chosen);
//backtrack
chosen.erase(chosen.length()-1,1);
S.insert(i,1,c);
}
}
return permutated_strings;
}
int main() {
//code
int test;
cin >> test;
while(test)
{
string S;
cin >> S;
vector<string> vec;
vector<string> ::iterator i;
vec = permute(S,"");
for(i=vec.begin();i!=vec.end();i++)
cout<<*i<<" ";
cout << "\n";
test--;
}
return 0;
}
When I am printing the vector in the permute function I am getting the right result but when I am printing the vector in main function it is empty. Can somebody please point me out the mistake I am doing.
You need to save result of recursive call of permute method.
auto result = permute(S,chosen);
permutated_strings.insert(permutated_strings.end(), result.begin(), result.end());
I got the mistake that I was doing. I really hate answering my own questions but it may help someone like me in the future.
I have changed -
vector<string> permutated_strings;
to
static vector<string> permutated_strings;
in the permute function so that previous returns from the recursive calls are not lost. By doing so I am getting the desired result.
Thanks everyone for pointing me to the mistake that I was doing.
EDIT
As suggested by #M.M that this solution may cause problem in future. And I have realized that if I give "test" value as 2 the final value in the permutated_strings will be from test=1 + test =2 which is not which I wanted. So this solution is not the perfect one. Instead I am accepting solution from #BartekPL.

Trying to add elements to a Vector classified with a Struct

I'm making a program to basically show the statistics about words the user enters. The rest of the program is fine so far, but I'm having a hard time adding words to a vector of type WordCount.
I have looked around and found several answers, which I would've thought could solve my issue, but I either get a very weird compiler error or it just does not work. I have tried using emplace_back and push_back with calls I thought was right. In essence, my problem code is as follows:
#include <iostream>
#include <string>
#include <vector>
using namespace std; //for simplicity here
struct WordCount {
string word;
int count;
//I have tried using this too:
WordCount(string _word, int _count) : word{_word}, count{_count} {}
};
//...//
void wordToVector(/**...**/,string addStr, vector<WordCount>& wordStats){
/**... code that I've tested to work; basically determined if the
word was already said as I need to have unique words only...**/
wordStats.push_back(WordCount(addStr, 1));
/** also tried: (some had "#include <istream>" when using emplace_back
but that didn't seem to make a difference for me in any case)
wordStats.emplace_back(WordCount(addStr, 1));
wordStats.emplace_back({addStr, 1});
wordStats.push_back(addStr, 1)
wordStats.push_back(addStr).word; (and wordStats.push_back(1).count;)
**/
}
int main() {
vector<WordCount> wordStats(1); //"1" to initialize the size
wordStats.at(0).word = "";
wordStats.at(0).count = 0;
/**There's already a part to change the first values to what they should
be, and it worked last I tested it. Below is a part was for my
personal use to see if anything came out... if it worked**/
for (int i = 0; i < 3; i++) {
cout << wordStats.at(i).word << endl;
cout << wordStats.at(i).count << endl;
}
return 0;
}
I must use a vector for this and cannot use pointers (as I've seen suggested) or #include <algorithm> per the instructions. If I typed in "Oh happy day!", it should be able to print (when fixed, with the current cout statements):
OH
1
HAPPY
1
DAY
1
(There's an earlier part that capitalizes every letter, which I tested to work).
This is my first post here because I'm lost. Please let me know if I provided too much or not enough. **Edited formatting
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct WordCount {
string word;
int count;
};
void wordToVector(string addStr, vector<WordCount>& wordStats){
for (int i = 0; i < wordStats.size(); i++) {
if (wordStats[i].word == addStr) {
wordStats[i].count = wordStats[i].count + 1;
return;
}
}
struct WordCount wc;
wc.word = addStr;
wc.count = 1;
wordStats.push_back(wc);
}
int main() {
vector<WordCount> wordStats;
wordToVector("hehe", wordStats);
wordToVector("hehe", wordStats);
wordToVector("haha", wordStats);
for (int i = 0; i < wordStats.size(); i++) {
cout << wordStats.at(i).word << endl;
cout << wordStats.at(i).count << endl;
}
return 0;
}
Using this code I get output:
hehe
2
haha
1
Is there anything else that needs to be added?
If you want to split the input by the spaces and check for occurrences of every word in the input it could be quite inefficient for longer texts to check for every word (Would be linear I think with M*N complexity), so if you are allowed I do suggest to use a map with word as key and value as the amount of occurrences - or something in that fashion.

Balance ordering parenthesis via Dynamic programing

Hi from the very famous book Code to Crack i come across a question :
Implement an algorithm to print all valid (e.g., properly opened and closed) combinations of n-pairs of parentheses.
Example:
input: 3 (e.g., 3 pairs of parentheses)
output: ()()(), ()(()), (())(), ((()))
#include <iostream>
#include <string>
using namespace std;
void _paren(int l,int r,string s,int count);
void paren(int n)
{
string s="";
_paren(n,n,s,n);
}
void _paren(int l,int r,string s,int count){
if(l<0 || r<0)
return;
if(l==0 && r==0)
cout<<s<<endl;
else{
if(l>0)
{
_paren(l-1,r,s+"(",count+1);
}
if(r>l)
_paren(l,r-1,s+")",count+1);
}
}
int main(){
int n;
cin>>n;
paren(n);
return 0;
}
This is a recursive approach I tried for it . I am pretty sure that we can solve this through dynamic programming as well , as we are already using a lot of value again and again , but I have no idea how to implement this through Dynamic programming I tried tabular bottom up approach but couldnt work out. Please help me out just the basic idea on how to work with this
DP does not really help you. The recursive algorithm is time and space optimal!
In fact, there is a reason not to use DP: the memory requirements! This will be huge.
A better algorithm is to have one character array that you pass in, have the recursive method modify parts of it and print that when needed. I believe that solution is given in the book you mention.
DP can reduce count of traversed states by choosing the optimal solution every call. It also help you to reuse calculated values. There is no calculations, every valid state must be visited, and non-valid states can be avoided by if( ).
I suggest you to implement some another recursion (at least without copying new string object after call, just declare global char array and send it to output when you need).
My idea of recursion is
char arr[maxN]; int n; // n is string length, must be even though
void func(int pos, int count) { // position in string, count of opened '('
if( pos == n ) {
for(int i = 0; i < n; i++)
cout << char(arr[i]);
cout << "\n";
return;
}
if( n-pos-1 > count ) {
arr[pos] = '('; func(pos+1,count+1);
}
if( count > 0 ) {
arr[pos] = ')'; func(pos+1,count-1);
}
}
I didn't checked it, but the idea is clear I think.

Modifying a recursive string reverse function

I am doing some recursive exercises. The previous one was to make a reverse() function for a string which basically removes the first character and then combines the solution. I managed to do that, here is the source code (the entire source) The current task is to modify this function (the following exercise in the book) by adding a helper function which reverses a substring of the string. At this moment I am stuck at this. It is my understanding that you use helper functions when you need to pass additional arguments or something and this function takes none so I really have no idea how to approach this problem. Help appreciated.
#include <iostream>
#include <string>
using namespace std;
void reverse(string& text)
{
if (text.length() == 0)
{
return;
}
if (text.length() == 1)
{
return;
}
else
{
string firstLetter = text.substr(0,1);
text = text.substr(1, text.length()-1);
reverse(text);
text += firstLetter;
}
}
int main()
{
string a = "tyu";
reverse(a);
cout << a << endl;
return 0;
}
A guy suggested to use parameters, ect, this is my try with it:
#include <iostream>
#include <string>
using namespace std;
//is actually doing the hard work
void reverse1(string& input, int a, int b)
{
// base case
if( a >= b)
{
return;
}
//swap the characters
char tmp;
tmp = input[a];
input[a] = input[b];
input[b] = tmp;
//create the boundries for the new substring
a++;
b--;
//call the function again
reverse1(input, a, b);
}
// sets the parameters and calls the helper function
void strreverse(string& input)
{
reverse1(input, 0, input.length()-1);
}
int main()
{
cout << "Please enter the string which you want to be reversed:";
string a;
cin >> a;
strreverse(a);
cout << a << endl;
return 0;
}
The goal is probably to avoid creating all of the intermediate substrings. The helper function will take iterators, or a start and end index in addition to the string begin reversed.
Try to implement reversing so that there is only one instance of std::string (i.e. work with it as with an array). Then you will need a helper function with additional parameters (at least one parameter - which index to reverse now).
I would implement reverse here as series of exchanges: a[0] <-> a[n-1], a[1] <-> a[n-2] etc. where n is length of the string.
You can define a helper function that takes a start and an end index of the substring which it will reverse.
The function should exchange the element at the start index with that at the end index IFF the difference between the start and the end indices is 1. Otherwise, it places a recursive call to itself by decrementing the end index and incrementing the start index. You will need to keep check on the condition if the start and end index become same though.

Mysterious Segmentation fault in string reversal

I'm writing a piece of code meant to reverse strings using recursion. I believe my method is correct, but I keep getting a segmentation fault and I'm not sure where it's coming from. All my research indicates that it means I'm doing "something strange with memory". I'm new enough at this that these kinds of errors are still baffling, so any help here would be much appreciated. Here's my code:
#include <iostream>
#include <string>
using namespace std;
class Palindrome
{
int front;
int back;
public:
Palindrome();
string reverse(string word)
{
int len = word.length()-1;
if (back == 0) {
back = len;
}
if (front >= back)
return word;
else{
char first = word[front];
char last = word[back];
word[front] = last;
word[back] = first;
front += 1;
back -= 1;
reverse(word);
}
}
};
Palindrome::Palindrome(){
front = 0;
back = 0;
}
I tried your code and got an "access violation" too, even with only one call. Beside the initialization issue described in other answers and comments, what is causing your seg fault is the missing "return" before your recursive call to "reverse". You need to write return reverse(word);
In Visual Studio, your original code gives this: warning C4715: 'Palindrome::reverse' : not all control paths return a value.
See this question for more details.
Here's a version of reverse() with both fixes:
string reverse(string word)
{
int len = word.length()-1;
if (back == 0)
{
back = len;
}
if (front >= back)
{
front = 0;
back = 0;
return word;
}
else
{
char first = word.at(front);
char last = word.at(back);
word.at(front) = last;
word.at(back) = first;
front += 1;
back -= 1;
return reverse(word);
}
}
What I think Jacob Abrahams was trying to say, front is iterated, but never re-set to zero, so the second time you call it, it will either segfault or produce incorrect results depending on whether the second word is longer or shorter.
Furthermore, what Mark B already hinted at is that you can include algorithm and replace the whole Palindrome::reverse function with
std::reverse(word.begin(), word.end());
Most of all it would help if you learned how to use a debugger or, in the future, at least give the specific error message for these kinds of questions.
EDIT: Forgot to add that recursion (e.g. a function calling itself) is usually a bad idea, because the execution stack is quite small and in this case, even after fixing the aforementioned issue, you will get a stack overflow for a particularly long string. It actually makes this particular code less clear.
Personally, I consider mixing recursion and objects somewhat odd. One of the fundamental concepts of objects is that the object holds state that you want to keep track of. One of the fundamental concepts of recursion is that the execution stack holds the state you want to keep track of.
In this case, the state you want to keep track of is how much of the string has been processed/how much of the string remains to be processed. You can keep track of that without an object.
This smells a lot like a homework question. But I can't think of a hint to give you without just handing you the answer. The best I can do is make my answer (1) reverse any container, including but not limited to strings; (2) use an STL-like interface (i.e., iterators); and (3) reverse the string in place instead of reversing a copy of the string:
#include <algorithm> // std::swap
// the other headers are only for my example on how to use the code
#include <iostream>
#include <iterator>
#include <string>
#include <list>
template<typename Itor> void reverse_with_recursion(Itor begin, Itor end)
{
using std::swap; // same trick used by the STL to get user-defined swap's,
// but fall back to std::swap if nothing else exists:
// http://en.wikipedia.org/wiki/Argument-dependent_name_lookup#Interfaces
// if begin and end are pointing at the same element,
// then we have an empty string and we're done
if (begin == end) {
return;
}
// the STL follows the pattern that end is one element after
// the last element; right now we want the last element
--end;
// if begin and end are pointing at the same element *now*,
// then we have a single character string and we're done
if (begin == end) {
return;
}
swap(*begin, *end);
return reverse_with_recursion(++begin, end);
}
int main()
{
std::string foo("hello world");
reverse_with_recursion(foo.begin(), foo.end());
std::cout << foo << '\n';
std::list<int> bar;
for (int i = 0; i < 10; ++i) {
bar.push_back(i);
}
reverse_with_recursion(bar.begin(), bar.end());
std::copy(bar.begin(),
bar.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';