I was trying to test my self and wanted to write mergesort, without actually looking up any code online, and to do it in a certain time period. I am stuck at this point where I cannot simply understand what I am doing wrong, since merge sort, as much as i remember, is to divide the strings up to the point where string is only 1 character and later on merge them back together. The code I've written below tries to do the exact thing. I was wondering whether I got the concept wrong, or just my implementation?
string merge(string str1, string str2) {
string final = "";
int i = 0, j = 0;
bool fromStr1 = false;
while(true) {
if(str1[i] < str2[j]) {
final += str1[i];
i++;
if(i == str1.size()) {
break;
}
}
else {
final += str2[j];
j++;
if(j == str2.size()) {
break;
fromStr1 = true;
}
}
}
if(fromStr1) {
for(int t = i; t < str1.size(); t++) {
final += str1[t];
}
}
else {
for(int t = j; t < str2.size(); t++) {
final += str2[t];
}
}
return final;
}
string mergeSort(string str1, int start, int end) {
if(end - start == 1)
return str1;
else {
int pivot = (end - start) / 2;
string newStr1 = mergeSort(str1, start, pivot);
string newStr2 = mergeSort(str1, pivot + 1, end);
return merge(newStr1, newStr2);
}
}
Note the changes:
#include <iostream>
#include <string>
using namespace std;
string merge(string str1, string str2) {
string final = "";
int i = 0, j = 0;
bool fromStr1 = false;
while (true) {
if (i >= (int)str1.size()) {
break;
}
if (j >= (int)str2.size()) {
fromStr1 = true; // changed the order of this with break!
break;
}
if (str1[i] < str2[j]) {
final += str1[i];
i++;
}
else {
final += str2[j];
j++;
}
}
if (fromStr1) {
for (int t = i; t < (int)str1.size(); t++) {
final += str1[t];
}
}
else {
for(int t = j; t < (int)str2.size(); t++) {
final += str2[t];
}
}
return final;
}
string mergeSort(string str1) {
int len = str1.size();
if (len <= 1)
return str1;
else {
string newStr1 = mergeSort(str1.substr(0, len / 2));
string newStr2 = mergeSort(str1.substr(len / 2, len - len / 2));
return merge(newStr1, newStr2);
}
}
int main()
{
cout << '"' << mergeSort("") << '"' << endl;
cout << '"' << mergeSort("a") << '"' << endl;
cout << '"' << mergeSort("ba") << '"' << endl;
cout << '"' << mergeSort("132") << '"' << endl;
cout << '"' << mergeSort("4321") << '"' << endl;
cout << '"' << mergeSort("54321") << '"' << endl;
return 0;
}
Output (ideone):
""
"a"
"ab"
"123"
"1234"
"12345"
This doesn't look right:
int pivot = (end - start) / 2;
string newStr1 = mergeSort(str1, start, pivot);
string newStr2 = mergeSort(str1, pivot + 1, end);
Don't you mean pivot=(end+start)/2? Or else mergeSort(str1, start, start+pivot) and mergeSort(str1, start+pivot+1, end)?
EDIT:
And your merge doesn't cope well with empty strings. You should have tested this function before hooking it up to mergeSort.
It's been ages since I used C++, but doesn't break immediately exit the loop? Because fromStr1 = true; is never reached in that case.
Related
I was working on a leetcode problem to reverse a string such that such that if Input is The boy is mad, the output should be mad is boy The. I solved it but the solution seemed poor as I was running through the string a lot of times. On submitting the code, the time taken to compute all the test cases was ~250ms, and I believed it as I knew this was the worst possible code. I looked up one of the answers and ran that code, it ran in like 4ms. I wrote the same code again, but this time I used a = a + b; instead of a += b;, and the test cases again took around 250ms. So, I want to know what is the difference between these two and why does it take a long time on one when compared to the other.
PS - In my original (poor) code, on changing a = a + b to a += b, the code ran in like 8ms.
Here are the codes:
1. slow code(runtime - ~250 ms)
string reverseWords(string s) {
if(s.length() == 0)
{
return s;
}
int itr = 0;
// Remove white spaces from front
while(s[itr] == ' ')
{
itr++;
}
s = s.substr(itr,s.length()-itr);
if(s.length() == 0)
{
return s;
}
// Remover white spaces from back
for(int i = s.length()-1; i>= 0 ;i--)
{
while(s[i] == ' ')
{
s = s.substr(0,i);
i--;
//cout << s << endl;
}
break;
}
if(s.length() == 0)
{
return s;
}
cout << s << endl;
// Remove more than one space in the middle
for(int i = 0;i<s.length()-1;i++)
{
if(s[i] == ' ' && s[i+1] == ' ')
{
string temp;
temp = s.substr(0,i);
s = s.substr(i+1,s.length());
s = temp + s;
i--;
//cout << s <<endl;
}
}
string res = "";
reverse(s.begin(),s.end());
int start = 0;
for(int i = 0;i <s.length();i++)
{
start = i;
if(s[i] == ' ')
continue;
while(s[i] != ' ' && i < s.length())
{
i++;
// cout << i << " ";
}
// cout << endl;
string temp = s.substr(start,i-start);
reverse(temp.begin(),temp.end());
if(i != s.length())
res = res + temp + " ";
else
res = res + temp;
//cout << temp << endl;
}
return res;
}
Fast code(4ms)
string reverseWords(string s)
{
stack<string> elements;
std::istringstream stream(s);
std::string word;
while (stream >> word)
{
elements.push(word);
}
string strReturn("");
int stackSize = elements.size();
int i = 0;
while( !elements.empty())
{
i++;
strReturn += elements.top();
elements.pop();
if( i != stackSize)
{
strReturn += " ";
}
}
return strReturn;
}
Re written Fast code(250ms)
string reverseWords(string s) {
// Check the first available Accepted solution to see the shitiest solution for the code
stack<string> availableWords;
istringstream stream(s);
string word;
while(stream >> word)
{
availableWords.push(word);
}
int len = availableWords.size();
string res = "";
int i = 0;
while(!availableWords.empty())
{
res += availableWords.top();
availableWords.pop();
i++;
if(i != len)
{
res += " ";
}
}
return res;
}
In this question, we take 2 strings as input say s1 and s2.
Now, first we need to check if s2 is a subsequence of s1. If not, print no.
But if it is, we need to print the minimum number of characters to be deleted from s1 to get s2.
Eg- thistext text
Here, text can be directly found without deleting any characters so the answer is 0.
Eg- cutefriendship crisp
In this case, the answer is 9.
What I've done so far,
#include <bits/stdc++.h>
using namespace std;
int checkIfSub(string s1, string s2, int m, int n)
{
int j = 0;
for(int i = 0; i < m && j < n; i++)
if(s1[i] == s2[j])
j++;
if(j == n)
return 0;
else
return 1;
}
int check(string s1, string s2)
{
int count = 0; string s3;
if(checkIfSub(s1, s2, s1.length(), s2.length()) == 1 || s2.length() > s1.length())
{
cout << "NO\n"; return 0;
}
int j = 0;
for(int i = 0; i < s1.length(); i++)
{
if(s1[i] == s2[j])
{
s3[j] = s1[j];
j++; continue;
}
count++;
}
cout << "YES " << count << "\n";
return 0;
}
int main() {
string s1, s2;
cin >> s1 >> s2;
check(s1, s2);
return 0;
}
My code works well for the second example, but fails the first case.
(This was a question asked in some interview I read online.)
Try something like this:
#include <iostream>
#include <string>
using namespace std;
bool check(const string &s1, const string &s2, int &minToDelete)
{
minToDelete = 0;
bool anySubSeqFound = false;
if (s2.empty())
return false;
string::size_type first = 0;
while ((first = s1.find(s2[0], first)) != string::npos)
{
int numDeleted = 0;
bool isSubSeq = true;
string::size_type next = first + 1;
for(string::size_type j = 1; j < s2.size(); ++j)
{
string::size_type found = s1.find(s2[j], next);
if (found == string::npos)
{
isSubSeq = false;
break;
}
numDeleted += (found - next);
next = found + 1;
}
if (isSubSeq)
{
if (anySubSeqFound)
{
if (numDeleted < minToDelete)
minToDelete = numDeleted;
}
else
{
anySubSeqFound = true;
minToDelete = numDeleted;
}
}
++first;
}
return anySubSeqFound;
}
int main()
{
int minToDelete;
if (check("thistext", "text", minToDelete))
cout << "yes, delete " << minToDelete << endl;
else
cout << "no" << endl;
if (check("cutefriendship", "crisp", minToDelete))
cout << "yes, delete " << minToDelete << endl;
else
cout << "no" << endl;
}
Live Demo
I'm working on an assignment. I have coded the assignment and everything is working as it should, except my output is missing a digit. I also attached the sample output. After inputting a a mathematical expression into a string, for example 35 * 4 - 6 / (9 + 3), a digit is dropped. In normal order, the 3 will be missing. In reverse order, the 9 will be missing. I am not understanding why this happening.
Any help, or I would prefer some guidance, would be appreciated. Am I using the push_back incorrectly? The code is as follows:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
vector<string> split(string);
vector<string> splitback(string);
int main()
{
vector<string> vectorExpression;
string expression;
cout << "Enter an expression :";
getline(cin, expression);
vectorExpression = split(expression);
for (int i = 0; i < vectorExpression.size(); i++)
{
cout << vectorExpression[i] << endl;
}
cout << endl;
vectorExpression = splitback(expression);
for (int i = 0; i < vectorExpression.size(); i++)
{
cout << vectorExpression[i] << endl;
}
system("pause");
return 0;
}
vector<string> split(string expression)
{
vector<string> splitExpression;
string digit = "",
x = "";
for (int i = 0; i < expression.size(); i++)
{
if (expression[i] >= '0' && expression[i] <= '9')
{
digit = digit + expression[i];
}
else if (expression[i] != ' ')
{
x = "";
x = x + expression[i];
splitExpression.push_back(x);
}
else
{
if (digit.size() > 0)
{
splitExpression.push_back(digit);
digit = "";
}
}
}
if (digit.size() > 0)
{
splitExpression.push_back(digit);
}
return splitExpression;
}
vector<string> splitback(string expression)
{
vector<string> splitBackExpression;
string number = "",
x = "";
for (int i = expression.size() - 1; i >= 0; i--)
{
if (expression[i] >= '0' && expression[i] <= '9')
{
number = expression[i] + number;
}
else if (expression[i] != ' ')
{
x = "";
x = x + expression[i];
splitBackExpression.push_back(x);
}
if (number.size() > 0)
{
splitBackExpression.push_back(number);
number = "";
}
}
return splitBackExpression;
}
Your split function is wrong, you forget to add digits, correct one would be
vector<string> split(string expression)
{
vector<string> splitExpression;
string digit = "",
x = "";
for (int i = 0; i < expression.size(); i++)
{
if (expression[i] >= '0' && expression[i] <= '9')
{
digit = digit + expression[i];
}
else
{
// don't forget digit if there was one
if (digit.size() > 0)
{
splitExpression.push_back(digit);
digit = "";
}
// also add what comes next if not a whitespace
if (expression[i] != ' ')
{
x = expression[i];
splitExpression.push_back(x);
}
}
}
if (digit.size() > 0)
{
splitExpression.push_back(digit);
}
return splitExpression;
}
Here is the final answer to my own question, or at least the solution I came up with the help from here.
#include<iostream>
#include<string>
#include<vector>
using namespace std;
vector<string> split(const string&);
vector<string> splitback(const string&);
int main()
{
vector<string> forwardExpression,
reverseExpression;
string expression;
cout << "Enter an expression :";
getline(cin, expression);
//////////////////////////////////////////////////
// FORWARD DISPLAY OF EXPRESSION //
//////////////////////////////////////////////////
forwardExpression = split(expression);
cout << "'" << expression << "'" << " split into individual entities forwards
yields:" << endl;
cout << endl;
for (int i = 0; i < forwardExpression.size(); i++)
{
cout << forwardExpression[i] << endl;
}
cout << endl;
//////////////////////////////////////////////////
// BACKWARD DISPLAY OF EXPRESSION //
//////////////////////////////////////////////////
reverseExpression = splitback(expression);
cout << "'" << expression << "'" << " split into individual entities
backwards yields:" << endl;
cout << endl;
for (int i = 0; i < reverseExpression.size(); i++)
{
cout << reverseExpression[i] << endl;
}
cout << endl;
system("pause");
return 0;
}
//////////////////////////////////////////////////
// FORWARD FUNCTION OF EXPRESSION //
//////////////////////////////////////////////////
vector<string> split(const string &expression)
{
vector<string> splitExpression;
string digit = "",
x = "";
for (int i = 0; i < expression.size(); i++)
{
if (expression[i] >= '0' && expression[i] <= '9')
{
digit = digit + expression[i];
}
else
{
if (digit.size() > 0)
{
splitExpression.push_back(digit);
digit = "";
}
if (expression[i] != ' ')
{
x = expression[i];
splitExpression.push_back(x);
}
}
}
if (digit.size() > 0)
{
splitExpression.push_back(digit);
}
return splitExpression;
}
//////////////////////////////////////////////////
// BACKWARD FUNCTION OF EXPRESSION //
//////////////////////////////////////////////////
vector<string> splitback(const string &expression)
{
vector<string> splitBackExpression;
string digit = "",
x = "";
for (int i = expression.size() - 1; i >= 0; i--)
{
if (expression[i] >= '0' && expression[i] <= '9')
{
digit = expression[i] + digit;
}
else
{
if (digit.size() > 0)
{
splitBackExpression.push_back(digit);
digit = "";
}
if (expression[i] != ' ')
{
x = expression[i];
splitBackExpression.push_back(x);
}
}
}
if (digit.size() > 0)
{
splitBackExpression.push_back(digit);
}
return splitBackExpression;
}
I cant get the char search to work. The substring function is working but the char search won't provide the right location of the char it is looking for
#include<iostream>
#include <string>
using namespace std;
int charsearch(string searchInto, char ch, int start = 0)
{
int x = 0;
long n = searchInto.length();
for (int i = 1; i < n; i++)
{
cout << ch;
if (searchInto[i] == ch)
{
i = x;
}
else
i++;
}
cout<< x;
return x;
}
int substr(string src, string tosearch, int start = 0)
{
string searchInto = src;
long n = searchInto.size();
long m = tosearch.size();
int ans = -1;
for (int i = start; i < n; ++i)
{
int p = i;
int q = 0;
bool escape = false;
while (p < n && q < m) {
if (searchInto[p] == tosearch[q]) {
if (tosearch[q] == '/' && !escape) {
++q;
} else {
++p; ++q;
}
escape = false;
} else if (!escape && tosearch[q] == '*') {
++q;
while (q < m && p < n && searchInto[p] != tosearch[q]) ++p;
escape = false;
} else if (!escape && tosearch[q] == '?') {
++p; ++q;
escape = false;
} else if (tosearch[q] == '/' && !escape) {
escape = true;
++q;
} else break;
}
if (q == m) {
return i;
}
if (q == m - 1 && tosearch[q] == '*') {
if (q > 0 && tosearch[q - 1] == '/') continue;
else return i;
}
}
return ans;
}
int main()
{
string searchInto, tosearch;
cout<< "Enter string:";
getline(cin, searchInto);
cout << "Looking for :";
getline(cin, tosearch);
if (tosearch.length() < 2)
{
char ch = tosearch.at(0);
cout << "Found at: " <<charsearch(searchInto, ch) << endl;
cout << "Used Char" << endl;
}
else
cout << "Found at: " <<substr(searchInto, tosearch) << endl;
return 0;
}
To find a character in a string, you have two interfaces.
std::string::find will return the position of a character you find:
auto pos = yourStr.find('h');
char myChar = yourStr[pos];
If the character does not exist, then std::string::npos will be returned as the std::size_t returned for position.
stl algorithm std::find, in header algorithm returns an iterator:
auto it = std::find(yourStr.begin(), yourStr.end(), 'h');
char myChar = *it;
If the character does not exist, then it == yourStr.end().
There are some silly mistakes in your CharSearch method. First of all, You have to break the loop when you got your target character. And most importantly you are not assigning x when you are finding the target. Furthermore, there is extra increment of value i inside the loop. I have modified the function. Please check it below
int charsearch(string searchInto, char ch, int start = 0) {
int x = -1;
long n = searchInto.length();
for (int i = start; i < n; i++)
{
cout << ch;
if (searchInto[i] == ch)
{
x = i; // previously written as i = x which is wrong
break; // loop should break when you find the target
}
}
cout<< x;
return x;
}
Please note that,you can either also use find method of string or std::find of algorithm to search in string.
You need to make changes as per this code
int charsearch(string searchInto, char ch, int start = 0)
{
int x = -1; // : change, if return -1, means not found
long n = searchInto.length();
for (int i = start; i < n; i++) // : change
{
cout << ch;
if (searchInto[i] == ch)
{
x = i; // : change
break; // : change
}
}
cout<< x;
return x;
}
Note : This function will return 1st match.
I have been trying to make an anagram maker, using a textBox (encryption_text) for input, which the text is "Hello World", and the output textBox (encrypted_text) which receives the text:
"ellllloooo
WWWWWWooooooorrrrrrrrllllllllldddddddddd".
I also have a textBox called 'anag_used', which should record the used number/location in the string to encrypt.
Have I over complicated it, or is there an error?
Thanks :)
Here is my code:
void anagram()
{
string toanagram = marshal_as<string>(encryption_text->Text);
string out;
int k;
System::String^ rndstr;
System::String^ ktostr;
ostringstream kstr;
anag_used->Clear();
for (int i = 0; i < toanagram.size(); ++i)
{
anag_used->Text += "\n";
int rnd = 0 + rand() % toanagram.size();
ostringstream rndtostr;
rndtostr << rnd;
rndstr = gcnew System::String(rndtostr.str().c_str());
for (int l = 0; l < i; ++l)
{
if (anag_used->Lines[l] == rndstr)
{
k = rnd;
kstr << k;
ktostr = gcnew System::String(kstr.str().c_str());
for (System::String^ j = anag_used->Lines[l]; j == ktostr; k = 0 + rand() % toanagram.size())
{
kstr << k;
ktostr = gcnew System::String(kstr.str().c_str());
if (anag_used->Lines[l] == ktostr)
{
//Do someting if you want
}
else
{
out += toanagram[k];
anag_used->Lines[l] = ktostr;
}
}
}
else
{
out += toanagram[i];
anag_used->Lines[i] = rndstr;
}
}
}
encrypted_text->Text = marshal_as<System::String^>(out);
}
EDIT: FOUND A MUCH SIMPLER WORKING CODE
#include <algorithm>
.
string toanagram = marshal_as<string>(encryption_text->Text);
sort(toanagram.begin(), toanagram.end());
encrypted_text->Text = marshal_as<System::String^>(toanagram);
This works for console, but you could implement it in C++/CLI quite easily
#include <iostream>
#include <sstream>
#include <vector>
#include <ctime>
void str_vect(std::vector<const char>* v, std::string& s)
{
for (int i = 0; i < s.length(); ++i)
{
v->push_back(s[i]);
}
}
int main()
{
for (;;)
{
std::cout << "Please enter the word / phrase\n";
std::string word;
std::getline(std::cin, word);
std::vector<const char> word_split;
str_vect(&word_split, word);
int sz = word_split.size();
std::string anagram;
for (int i = 0; i < sz; ++i)
{
srand(time(NULL));
int r = (rand() % (word_split.size() - 0)) + 0;
anagram += word_split[r];
word_split.erase((word_split.begin()) + r);
}
system("cls");
std::cout << "Please guess the anagrammed phrase / word - '" << anagram << "'\n";
int max_tries = 3;
int tries = max_tries;
for (int i = 0; i <= max_tries; ++i)
{
std::string guess;
std::getline(std::cin, guess);
if (guess != word)
{
tries--;
if (tries == 0)
{
std::cout << "You have ran out of tries. The answer was: " << word << "\n";
break;
}
std::cout << tries << ((tries == 1) ? " try" : " tries") << " left\n";
}
else
{
std::cout << "Correct!\n";
break;
}
}
}
}
#include <algorithm>
.
string toanagram = marshal_as<string>(encryption_text->Text);
sort(toanagram.begin(), toanagram.end());
encrypted_text->Text = marshal_as<System::String^>(toanagram);