Wrong Answer with Recursive Sum Task - c++

I am working on a problem to print all the non-increasing subsequences with sum equal to a given number n, using recursion. I know there is something wrong with my recursive algorithm, but I have walked through the process multiple times and I cannot find my error. With input 4, my code gives output:
4
431
4322
432211
43213
4321321
43213212
4321321211
I believe the recursion is holding on to previous numbers or sums used in past recursive calls, but cannot find why. Can anybody please help me figure out why the program is not giving correct output?
#include <iostream>
#include <string>
using namespace std;
int n;
void sums(int sum, string str)
{
if (sum==n)
{
cout << str << "\n";
return;
}
for (int i = n-sum; i >= 1; i--)
{
str+=to_string(i);
sums(sum+i, str);
}
}
int main()
{
cin >> n;
string s = "";
sums(0, s);
}

The problem is in your: str+=to_string(i); inside your for loop.
on the first call you have sum 0, str = "", and in the for loop it goes from i = 4, i--. but inside the body you append to str += 4 and call sums(4, "4"), and the error happens on the next loop i--, str += "3" and becomes "43" and sums(3, "43");
You can fix it by not modifying str, but calling
sums(sum + i, str + to_string(i));

From my understanding of recursive functions, I believe there should not be a loop at all! so, replace :
for (int i = n-sum; i >= 1; i--)
{
str+=to_string(i);
sums(sum+i, str);
}
by:
str+=to_string(n-sum);
sums(n-sum, str);

Related

How do you insert characters into middle of string? C++

The purpose of this code is to insert an x in between repeating letters. For example, if I were to input "CoolBoolFallmoose", the output would be "CoxolBoxolFalxlmoxose".
The code is also supposed to make an even number of pairs of letters, so if there is an odd amount of characters, an x is added to the end of the string. An example for this would be if we had "ball", it would become "balxlx" to make even pairs: "ba" "lx" "lx".
This is the code I have so far:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main(){
string cipher, plain, paired = "";
cout << "input plaintext(no spaces, lowercase):\n";
cin >> plain;
for (int i=0;i<plain.length();i++){
if (plain[i]==plain[i+1]){
plain.insert(i,'x');
}
paired[i]=paired[i];
cout<<paired[i];
}
if (paired.length() % 2!= 0){
paired=+'x';
}
cout<<paired<<endl;
return 0;
}
The output I get is just the same as my input, no "x" added in any place.
The issue I am having is, every time I try to use the append() or insert() function for strings, I get an error from my compiler, which is xCode. Is there another way to solve this code?
EDIT: The error says:
No matching member function to call for insert
It also comes up for append().
I don't really know what you wanted to do with this part:
paired[i]=paired[i];
cout<<paired[i];
but otherwise the logic is good. Here is my take on it, x is a counter:
#include <iostream>
#include <string>
using namespace std;
int main(){
string m,n;
int x = 0;
cout << "Input: " << endl;
getline(cin, m);
for(int i = 0;i < m.length();i++){
x++;
n = n + m[i];
if(m[i] == m[i+1]){
n = n + 'x';
x++;
}
}
if((x % 2) != 0){
n = n + 'x';
}
cout << n;
return 0;
}
If you look at the available overloads of std::string::insert(), you will see that your statement plain.insert(i,'x'); does not match any of them, hence the compiler error. The overloads that takes a single char require either:
an index and a count (you are omitting the count)
an iterator and an optional count
There is, however, a couple of overloads that take just an index and a value, but they require a const char* or a std::string, not a single char.
Also, paired[i]=paired[i]; is a no-op. Except in your case, since paired has a size() of 0 since you never append anything to paired, so actually any access to paired[...] is undefined behavior.
Try this instead:
#include <iostream>
#include <string>
using namespace std;
int main(){
string plain, paired;
cout << "input plaintext(no spaces, lowercase):\n";
cin >> plain;
paired = plain;
for (string::size_type i = 1; i < paired.size(); ++i){
if (paired[i] == paired[i-1]){
paired.insert(i, 1, 'x');
// or: paired.insert(paired.begin()+i, 'x');
// or: paired.insert(i, "x");
// or: paired.insert(i, string{'x'});
// or: paired.insert(paired.begin()+i, {'x'});
++i; // skip the x just inserted
}
}
if (paired.size() % 2 != 0){
paired += 'x';
}
cout << paired << endl;
return 0;
}
Demo
A couple of points
First, Although the string.insert function says it takes an int as its first argument it really wants an iterator in this case.
Second, you are inserting elements into your "plain" string which increases its length and you have plain.length within your loop so you create an infinite loop.
Third, insert inserts BEFORE the index so you need to add 1 to I.
The code below will work for your loop:
Int len = plain.length();
Int count = 0;
for (int i = 0; i < len + count; i++)
{
If (plain[i] == plain[i + 1])
{
plain.insert(plain.begin() + (i +1), 'X');
++count;
}
}
cout << plain;
And as, mentioned below, if you want to handle spaces you can use getline(cin, plain) instead of cin.

Reversing string using stack (static array) in c++

i am new to this concept in c++
i am trying to reverse string using stack static array implementation in c++.
Input: qwerty
expected output: ytrewq
output which i am getting is: trewq
Can some one explain me why is this happening and any possible solution.
Here's my code
#include <iostream>
#include <string>
using namespace std;
#define SIZE 10
string arr[SIZE];
unsigned a = -1;
void push(char ch) {
a = a + 1;
arr[a] = ch;
}
void pop() {
a = a - 1;
}
void display() {
for (int j = a; j >= 0; j--)
cout << arr[j];
}
int main() {
string str;
getline(cin, str);
for (int i = 0; i < (str.length() - 1); i++)
push(str[i]);
display();
}
Remove the "-1" in :
for(int i=0;i<(str.length())-1;i++)
Else your array doesn't contains the last character.
I made the test without the -1, it works well.
The condition "< str.length()" is enough to loop on all string caracter.
In similar case, use the debugger to see what contains your variable. In these case the variable "arr" don't contains the last input caracter.
You push everything on the stack, so the last element can be popped first. Then do popping to fill a reversed strng. The stack should be a char array.
As this is typically a task, the rest is your puzzle.
Pop typically gives you the top element as:
char pop() {
char ch = arr[a];
--a;
return ch;
}
The correct way to reverse a string would be to do:
std::reverse(str.begin(), str.end());
But I think this might be homework/study so look at your output. You are just missing the last letter. That suggests the upper limit of your loop is wrong doesn't it?

Printing out an unswapped array

I'm learning how to make myself a simple XOR encryption. However, to make things more difficult for a person to decipher the message I want to try to swap characters and then swap them back (after the user enters the key for the decryption).
This is my output:
yet ih ssia t se!t !
ey this is a test!!
Does anyone know why it is cutting off the h in the second printout? I'm still fairly new to programming and spent a good hour trying to figure it out.
Here is my code:
#include <cstring>
#include <string>
#include <iostream>
using namespace std;
void doSwap (char &string1, char &string2) {
char temp;
temp = string1;
string1 = string2;
string2 = temp;
}
int main() {
string content = "hey this is a test!!";
string after, after2;
int i;
for (i = 0; i < content.size(); i+=2) {
doSwap(content[i], content[i+2]);
}
after = content;
cout << after << "\n";
for (i = after.size(); i > 0; i -=2) {
doSwap(after[i], after[i-2]);
}
after2 = after;
cout << after2 << "\n";
}
Your loop indexing is not correct. As #tadman pointed out, you will walk off the string.
The first loop would have to terminate 2 indices shorter than the size, so that when you add 2, it would be 1 less than content.size(). Remember C/C++ is 0 indexed, therefore if size is 10, element 9 is the last index of the string.
for (i = 0; i < content.size()-2; i+=2) {
doSwap(content[i], content[i+2]);
}
Similarly the second loop should start 1 short of the size and terminate at 2, so when you index into i-2, you are indexing no less than 0.
for (i = after.size()-1; i >= 2; i -=2) {
doSwap(after[i], after[i-2]);
}

Why won't the final string show correct output when concatenate 2 string to a third one letter by letter?

/* Write a program that would mix-and-merge two given strings (s1 and s2) into string s3 as follows:
first character of s1, first character of s2, second character of s1, second character of s2, etc. */
I found this example exercise in the internet and i thought i would give it a try.
Everything seems to be ok and the code compiles without error but my "s3" string variable will not output anything and it will simply stay blank.
Funny to say but the problem seems to be here in the last line before return 0;
cout << s3;
If i do something like this:
cout << s3[0];
Or whatever index i want, it will show the correct character when the code is run which was joined from the other strings. So what is the problem?
Code here for reference:
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string s1, s2, s3;
int i;
int j = 0;
cout << "Type in the first string: ";
getline(cin, s1);
cout << "Type in the second string: ";
getline(cin, s2);
for(i = 0; j < s1.size(); i += 2) // Merge first string by starting at index 0 and moving in 2s hence i += 2.
{
s3[i] = s1[j];
++j;
}
j = 0;
for(i = 1; j < s1.size(); i +=2) // Merge second string by starting at index 1 hence i + 1 and again moving in 2s as to not overwrite an index that s1 put in.
{
s3[i] = s2[j];
++j;
}
cout << s3; // Problem is here?
return 0;
}
Accessing the s3 string using the operator [i] with i bigger than the current length is undefined behavior.
You could try making s3 big enough (e.g. fill with spaces) before your loops. Note that your current implementation only works if both strings are the same length.
Alternatively, try to think of a different way. e.g. the way you would do it if you had the strings s1 and s2 on little stacks of paper (with one letter on each piece) in front of you and wanted to merge them into a single stack.
Added just one line to your code and got this working:
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string s1, s2, s3;
size_t i;
size_t j = 0;
cout << "Type in the first string: ";
getline(cin, s1);
cout << "Type in the second string: ";
getline(cin, s2);
s3.resize(s1.size() + s2.size());
for(i = 0; j < s1.size(); i += 2) // Merge first string by starting at index 0 and moving in 2s hence i += 2.
{
s3[i] = s1[j];
++j;
}
j = 0;
for(i = 1; j < s1.size(); i +=2) // Merge second string by starting at index 1 hence i + 1 and again moving in 2s as to not overwrite an index that s1 put in.
{
s3[i] = s2[j];
++j;
}
cout << s3; // Problem is here?
return 0;
}
Although this works only for s1 and s2 of equal size.

I am getting replace was not declared in this scope

This is a function I am writing that switches the characters of a string, but I am getting "replace was not declared in this scope".
#include <string>
using namespace std;
string rs(string j)
{
srand(time(NULL));
int len = j.size();
int ran1 = rand() % len;
srand(time(NULL) + 1);
int ran2 = rand() % len;
replace(j, ran1, ran2);
cout << j << endl;
return j;
}
Obviously I have something wrong with the function. Any help is appreciated.
replace() is a member function of the string class which is most probably why you're getting the error.
But also, replace() doesn't switch the substrings, it just replaces one with the other.
If you want to switch two substrings of a string using the replace function, you can try doing it by replacing the line:
replace(j, ran1, ran2);
with
string substr_at_ran1 = j.substr(ran1, 1);
j.replace(ran1, 1, j.substr(ran2, 1));
j.replace(ran2, 1, substr_at_ran1);
This is switching the substring of j starting at position ran1 and length 1 with a substring of j at position ran2 and length 1.
Not enough information was provided to properly answer the question, but I'll take a stab at it.
The replace() function I'm assuming is a function that probably doesn't exist in your program, since you didn't provide it.
Assuming that you want your function rs() to randomly swap two characters, here is a program that does just that.
#include <string>
#include <iostream>
using namespace std;
string rs(string j)
{
auto len = j.size();
if (len == 0) //added because your code didn't account for empty strings
{
return j;
}
auto ran1 = rand() % len;
auto ran2 = rand() % len;
swap(j[ran1], j[ran2]);
cout << j << endl;
return j;
}
int main()
{
srand(time(NULL)); //do not use srand in modern C++!
rs("stack overflow");
}
I would also advise against making function names like rs, since its functionality cannot be gleaned from the name alone. swap_random_characters would be a better name.