I am trying to solve this problem:
https://www.geeksforgeeks.org/count-possible-decodings-given-digit-sequence/
Example:
Input:
Input str = "121"
Total decoding:: 3 :: ABA AU LA
I am able to code this problem through recursion. But the code fails to process a bigger input sequence (for e.g., i/p str = 11111111111111111111111111111111111111111)
This is happening because I am calculating sub-problems again-and-again.
Can anyone help me by letting me know how to memoize below sample code?
PS - I know there are other ways to solve this problem. But I don't want to do that. I want to memoize this solution only. It will help me to build my concept. Please help.
Here is the code:
#include "iostream"
#include <iostream>
#include <vector>
#include <string>
using namespace std;
namespace solution3
{
void solve(string str, string& out, vector<string>& v)
{
if (str.size() == 0)
{
v.push_back(out);
return;
}
//we have 2 choices:
//ch#1: take 1st char of str
//ch#2: take 1st and 2nd chars of str
if (str.size() >= 1)//ch#1: take 1st char of str
{
string out1 = out;
string str1 = str;
int num1 = stoi(str.substr(0, 1)); // converting string at index 0 to integer
if (num1) // we will not consider if the string at index 0 is zero.
{
out1.push_back(('#' + num1)); //<-- It will conevrt 1 into A; 2 into B; and so on.
str1 = str1.erase(0, 1);//erase the index 0 from str1.
solve(str1, out1, v);
}
}
if (str.size() >= 2)//ch#2: take 1st and 2nd chars of str
{
string out2 = out;
string str2 = str;
int num2 = stoi(str.substr(0, 2)); // converting string at index 0 and 1 to integer
// checking if num2 is a valid number for decoding.
// num2 should be - NON-ZERO, 1st char is not ZERO, is within the range of 1 and 26.
if (num2 && str[0] != '0' && num2 > 0 && num2 <= 26)
{
out2.push_back(('#' + num2));
//Erase 1st two chars from str
str2 = str2.erase(0, 1);//erase the index 0 from str1.
str2 = str2.erase(0, 1);//erase the index 0 from str1.
solve(str2, out2, v);
}
}
}
void alphacode(string str)
{
string out;
vector<string> v; //<-- To store all the Decodings
solve(str, out, v);
cout << "Total decoding:: " << v.size() << ":: ";
for (int i = 0; i < v.size(); i++)
cout << v[i] << " ";
cout << endl;
}
}
int main()
{
string str = "25114";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "1111111111";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "3333333333";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "202";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "2010";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "1111111111111111111111111111111"; //<-- takes too much time! How to solve this?
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
return 0;
}
You can memoize each substring that you are currently working with, which you're forming after deleting one or two characters, depending on the case. Something like this:
#include "iostream"
#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;
map<string, vector<string>> dp;
namespace solution3
{
void solve(string str, string& out, vector<string>& v)
{
if (str.size() == 0)
{
v.push_back(out);
return;
}
//we have 2 choices:
//ch#1: take 1st char of str
//ch#2: take 1st and 2nd chars of str
if(dp.find(str) != dp.end()) {
vector<string> current = dp[str];
for(string s: current) {
v.push_back(s);
}
return;
}
if (str.size() >= 1)//ch#1: take 1st char of str
{
string out1 = out;
string str1 = str;
int num1 = stoi(str.substr(0, 1)); // converting string at index 0 to integer
if (num1) // we will not consider if the string at index 0 is zero.
{
out1.push_back(('#' + num1)); //<-- It will conevrt 1 into A; 2 into B; and so on.
str1 = str1.erase(0, 1);//erase the index 0 from str1.
solve(str1, out1, v);
}
}
if (str.size() >= 2)//ch#2: take 1st and 2nd chars of str
{
string out2 = out;
string str2 = str;
int num2 = stoi(str.substr(0, 2)); // converting string at index 0 and 1 to integer
// checking if num2 is a valid number for decoding.
// num2 should be - NON-ZERO, 1st char is not ZERO, is within the range of 1 and 26.
if (num2 && str[0] != '0' && num2 > 0 && num2 <= 26)
{
out2.push_back(('#' + num2));
//Erase 1st two chars from str
str2 = str2.erase(0, 1);//erase the index 0 from str1.
str2 = str2.erase(0, 1);//erase the index 0 from str1.
solve(str2, out2, v);
}
}
dp[str] = v;
}
void alphacode(string str)
{
string out;
vector<string> v; //<-- To store all the Decodings
solve(str, out, v);
cout << "Total decoding:: " << v.size() << ":: ";
// for (int i = 0; i < v.size(); i++)
// cout << v[i] << " ";
cout << endl;
}
}
int main()
{
string str = "25114";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "1111111111";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "3333333333";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "202";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "2010";
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
cout << "----------------" << endl;
str = "1111111111111111111111111111111"; //<-- takes too much time! How to solve this?
cout << "IpStr:: " << str << endl;
solution3::alphacode(str);
return 0;
}
Related
I am writing the code which counts the lines in the document and split it into equal pats if the line more than 100. To split I am using string.substr(i, i+adding+ addCount). If i have to slit in three parts: First and third split part is OK, Second part has not only its part but also third part words in it. It looks something like this:
linesize: 331
divider3
0 Output I 110
1 EXPRESSION: Mrs. Bennet and her daughters then departed, and Elizabeth returned instantly to Jane, leaving her own and her
0 I
110I 110 0
was here OST
110 Output I 220
2 (error) EXPRESSION: relations’ behaviour to the remarks of the two ladies and Mr. Darcy; the latter of whom, however, could not be prevailed on to join in their censure of her, in spite of all Miss Bingley’s witticisms on fine eyes
110 I
220I 110 0
was here OST
220 Output I 416
3 EXPRESSION: be prevailed on to join in their censure of her, in spite of all Miss Bingley’s witticisms on fine eyes.
220 I
416I 110 86
was here OST
#include <iostream>
#include <deque>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <future>
#include <map>
#include <fstream>
#include <vector>
using namespace std;
atomic<bool> isReady{false};
mutex mtx;
condition_variable condvar;
map<string, int> mapper;
string line;
vector<string> block;
size_t line_index = 0;
int block_size = 100;
int limit_chars = 100;
int c = 0;
deque<vector<string>> dq;
void Producer() {
std::cout << " Producer " << std::endl;
fstream fl("/home/ostap/CLionProjects/WordsCount2/file.txt"); //full path to the file
if (!fl.is_open()) {
cout << "error reading from file" << endl;
}
else {
cout << "SUCCESS!!!" << endl;
while (getline(fl, line) && line_index < block_size) {
if (line.find_first_not_of(' ') != string::npos) { // Checks whether it is a non-space.
// There's a non-space.
cout<< "linesize: " << line.length() << endl;
if (line.length() / limit_chars > 1.4) {
int divider = (int) (line.length() / limit_chars);
int adding = (int) line.length()/divider;
//попробуй поміняти на while все через addCount
int addCount = 0;
int i = 0;
cout <<"divider" << divider<<endl;
while ( i < line.length()){
while (line[i + adding + addCount] != ' ') {addCount+=1;}
cout << i << " Output I " << i + adding + addCount << endl;
cout << "EXPRESSION: " << line.substr(i, i + adding + addCount) << endl; //to del
block.push_back(line.substr(i, i + adding + addCount));
cout << i << " I" << endl;
i = i + adding + addCount;
cout << i << "I" <<" " <<adding <<" "<< addCount <<endl;
++line_index;
addCount = 0;
cout << "was here OST" << endl;
}
}
else {
++line_index;;
block.push_back(line);
cout << "Line: " << line << endl;
}
if (line_index >= block_size) {
c++;
cout << c << endl;
{
lock_guard<mutex> guard(mtx);
//cout << "Producing message: " << x << " th" << endl;
dq.push_back(block);
}
line_index = 0;
block.clear();
}
condvar.notify_one();
}
cout << "Producer completed" << endl;
isReady = true;
// for (unsigned i = 0; i < block.size(); ++i) cout << ' ' << block[i];
// cout << '\n';
//this_thread::sleep_for(chrono::seconds(1));
}
}
}
void Consumer() {
while (true) {
unique_lock<mutex> lk(mtx);
if (!dq.empty()) {
vector<string> & i = dq.front();
dq.pop_front();
lk.unlock();
cout << "Consuming: " << i.data() << " th" << endl;
} else {
if(isReady){
break;
}
else {
condvar.wait(lk);
cout << "There are no messages remained from producer" << endl;
}
}
cout << "\nConsumer is done" << endl;
}
}
int main() {
//cout << "Hello, World!" << endl;
auto t1 = async(launch::async, Producer);
auto t2 = async(launch::async, Consumer);
//auto t3 = async(launch::async, Consumer);
t1.get();
t2.get();
//t3.get();
return -1;
So in this program I'm trying to go through word by word and make it only lowercase letters, no whitespace or anything else. However, my string "temp" isn't holding anything in it. Is it because of the way I'm trying to modify it? Maybe I should try using a char * instead? Sorry if this is a stupid question, I'm brand new to c++, but I've been trying to debug it for hours and can't find much searching for this.
#include <string>
#include <iostream>
#include <fstream>
#include <ctype.h>
using namespace std;
int main(int argc, char* argv[]) {
/*if (argc != 3) {
cout << "Error: wrong number of arguments." << endl;
}*/
ifstream infile(argv[1]);
//infile.open(argv[1]);
string content((std::istreambuf_iterator<char>(infile)),
(std::istreambuf_iterator<char>()));
string final;
string temp;
string distinct[5000];
int distinctnum[5000] = { 0 };
int numdist = 0;
int wordcount = 0;
int i = 0;
int j = 0;
int k = 0;
int isdistinct = 0;
int len = content.length();
//cout << "test 1" << endl;
cout << "length of string: " << len << endl;
cout << "content entered: " << content << endl;
while (i < len) {
temp.clear();
//cout << "test 2" << endl;
if (isalpha(content[i])) {
//cout << "test 3" << endl;
if (isupper(content[i])) {
//cout << "test 4" << endl;
temp[j] = tolower(content[i]);
++j;
}
else {
//cout << "test 5" << endl;
temp[j] = content[i];
++j;
}
}
else {
cout << temp << endl;
//cout << "test 6" << endl;
++wordcount;
final = final + temp;
j = 0;
for (k = 0;k < numdist;k++) {
//cout << "test 7" << endl;
if (distinct[k] == temp) {
++distinctnum[k];
isdistinct = 1;
break;
}
}
if (isdistinct == 0) {
//cout << "test 8" << endl;
distinct[numdist] = temp;
++numdist;
}
}
//cout << temp << endl;
++i;
}
cout << wordcount+1 << " words total." << endl << numdist << " distinct words." << endl;
cout << "New output: " << final << endl;
return 0;
}
You can't add to a string with operator[]. You can only modify what's already there. Since temp is created empty and routinely cleared, using [] is undefined. The string length is zero, so any indexing is out of bounds. There may be nothing there at all. Even if the program manages to survive this abuse, the string length is likely to still be zero, and operations on the string will result in nothing happening.
In keeping with what OP currently has, I see two easy options:
Treat the string the same way you would a std::vector and push_back
temp.push_back(tolower(content[i]));
or
Build up a std::stringstream
stream << tolower(content[i])
and convert the result into a string when finished
string temp = stream.str();
Either approach eliminates the need for a j counter as strings know how long they are.
However, OP can pull and endrun around this whole problem and use std::transform
std::transform(content.begin(), content.end(), content.begin(), ::tolower);
to convert the whole string in one shot and then concentrate on splitting the lower case string with substring. The colons in front of ::tolower are there to prevent confusion with other tolowers since proper namespacing of the standard library has been switched off with using namespace std;
Off topic, it looks like OP is performing a frequency count on words. Look into std::map<string, int> distinct;. You can reduce the gathering and comparison testing to
distinct[temp]++;
I'm working on a project which needs to find the number of words and the indices of each word in the paragraph ...I have written the code which is counting the number of word in a string but I stuck with finding the indices of words,
such as : Hi John How are you I miss you ..
I need to print the indices like : 0 1 2 3 4 5 6 7
here is the code:
int _tmain(int argc, _TCHAR* argv[])
{
int count_words(std::string);
std::string input_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
int number_of_words=1;
int counter []={0};
for(int i = 0; i < input_text.length();i++)
if(input_text[i] == ' ')
number_of_words++;
std::cout << "Number of words: " << number_of_words << std::endl;
//std:: cout << number_of_words << std::endl;
system ("PAUSE");
}
Hopefully this helps. Edited to include use of count_words function.
#include <iostream>
#include <sstream>
void count_words(std::string);
int main(){
std::string input_text, output_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
count_words(input_text);
system ("PAUSE");
return 0; //MUST RETURN AN INTEGER VALUE FROM 'INT MAIN'
}
void count_words(std::string inputString){
std::string output_text;
std::stringstream indexes;
int number_of_words=0; //If there are no words, it would be false, make it 0.
//int counter []={0}; //This serves no purpose.
if(!inputString.empty()){// test to make sure it isn't empty.
number_of_words++;
for(int i = 0; i < inputString.length();i++){ // For loops should have curly braces {} containing their statement.
if(inputString[i] == ' '){
number_of_words++;
}
if((isalpha(inputString[i]))&&inputString[i-1]==' '){ //test for following space separated word
indexes << i << " ";
}
}
}
output_text = indexes.str(); //convert stringstream to string
std::cout << "Number of words: " << number_of_words << std::endl;
//std:: cout << number_of_words << std::endl; //duplicate info
std::cout << "Indexes: " << output_text << std::endl;
}
I'm not sure if i understand the question. You only need print the "indices"?? like this? (Using your own code)
#include <iostream>
#include <vector>
#include <string>
void stringTokenizer(const std::string& str, const std::string& delimiter, std::vector<std::string>& tokens) {
size_t prev = 0, next = 0, len;
while ((next = str.find(delimiter, prev)) != std::string::npos) {
len = next - prev;
if (len > 0) {
tokens.push_back(str.substr(prev, len));
}
prev = next + delimiter.size();
}
if (prev < str.size()) {
tokens.push_back(str.substr(prev));
}
}
int main()
{
std::vector <std::string> split;
std::string input_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
stringTokenizer(input_text, " ", split);
int number_of_words = 0;
for (std::vector<std::string>::iterator it = split.begin(); it != split.end(); it++, number_of_words++) {
std::cout << *it << " " << number_of_words << std::endl;
}
}
I have a function that takes two strings and determines if they are the same. I am trying to tokenize the string and combine all of tokens into one string. This is what I have so far and I am getting Bus error :10.
any help appreciated.
#include <iostream>
#include <string>
using namespace std;
bool stringCheck(string s1, string s2){
string strCheck1 = "";
string strCheck2 = "";
char *cstr1 = new char[s1.length()]; // char array with length of string
strcpy(cstr1, s1.c_str()); // copies characters of string to char array
char *cstr2 = new char[s2.length()];
strcpy(cstr2, s2.c_str());
char *p1 = strtok(cstr1, " "); // creates a char array that stores token that
// is delimeted
cout << "p1 " << p1 << endl; ///outputs token that is found
strCheck1.append(p1); // appends token to string
cout << "strCheck1 " << strCheck1 << endl; // outputs string
while(p1 != NULL) // while the token is not a null character
{
cout<<"parsing" << endl;
p1 = strtok(NULL, " "); // continue to parse current string.
cout << "p1 " << p1 << endl;
strCheck1.append(p1);
cout << "str1 " << strCheck1 << endl;
}
char * p2 = strtok(cstr2, " ");
cout << "p2 " << p2 << endl;
strCheck2.append(p2);
cout << "strCheck2 " << strCheck2 << endl;
while(p2 != null){
p2 = strtok(NULL, " ");
strCheck2.append(p2);
cout << "str2 " << strCheck2 << endl;
}
if( strCheck1.compare(strCheck2) != 0)
{
return 0;
}
else return 1;
}
int main(void){
string s1 = "jam yoooo jay";
string s2 = "jam yoooo";
if(stringCheck(s1, s2) == 1){
cout << "strings same"<< endl;;
}
else{
cout << "strings not same" << endl;
}
}
is there a conditional statement I could pair up with
while(p1 != NULL)
I know this is a pretty silly function but just trying to polish up my skills. any help appreciated!
There are some things you must change:
char *cstr1 = new char[s1.length()];
c-string are null-terminated, so you need one more char to store the null character:
char *cstr1 = new char[s1.length() + 1];
(same for cstr2)
strCheck1.append(p1)
p1 cannot be a null pointer (see Assign a nullptr to a std::string is safe? for further details). So you have to check...
if (p1) strCheck1.append(p1);
(same for p2).
cout << p1 << endl
if p1 is a null pointer bad things can happen (see Why does std::cout output disappear completely after NULL is sent to it). So you have to check...
if (p1) { cout << "p1 " << p1 << endl; strCheck1.append(p1); }
(same for p2)
there is a memory leak (cstr1 / cstr2 must be deleted).
At the end it should work.
Probably you should consider other systems to extract tokens (where you haven't to mix std::string and c-string). E.g.:
#include <iostream>
#include <string>
#include <sstream>
int main()
{
std::string text("text-to-tokenize");
std::istringstream iss(text);
std::string token;
while(getline(iss, token, '-'))
std::cout << token << std::endl;
return 0;
}
This is a part of a program that I am writing to compute the addition of two integers as strings. (Writing my own bigInt class).
There appears to be a problem when I am adding the two integers together. Because they are both in vectors of char type, I had to add a '0' to each element of the vector before concatenating it into a string.
However, the results are still not what I am expecting:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string const Number = "1000";
string const Number2 = "1000";
vector<char> reverse;
vector<char> reverse2;
//cout << (rostrNumber[1] - '0') << endl;
cout << "Original Number: " << Number << endl;
reverse.clear();
for (int i = Number.size() - 1; i >= 0; i--)
{
reverse.push_back(Number[i]);
}
cout << "Reversed: " << endl;
cout << reverse[0] << reverse[1] << reverse[2] << reverse[3] << endl;
cout << endl << endl;
reverse2.clear();
{
for (int i = Number2.size() - 1; i >= 0; i--)
{
reverse2.push_back(Number[i]);
}
}
cout << "Adding these two integers" << endl;
vector<char> const rcvN1 = reverse;
vector<char> const rcvN2 = reverse2;
vector<char> Results;
Results.clear();
//Local copies
vector<char> vN1 = rcvN1;
vector<char> vN2 = rcvN2;
int iSize1 = vN1.size();
int iSize2 = vN2.size();
int i, iSize = iSize2;
int iC = 0, iR;
for (i = 0; i<iSize; i++)
{
iR = vN1[i] + vN2[i] + iC;
if (iR > 9)
{
iR -= 10;
iC = 1;
}
else
iC = 0;
Results.push_back(iR);
cout << Results[0] << endl;
}
if (iC > 0)
Results.push_back(iC);
string ostr;
vector<char>::const_reverse_iterator rIter = Results.rbegin();
for (; rIter != Results.rend(); rIter++)
ostr += *rIter +'0';
cout << "Results: " << ostr << endl;
system("PAUSE");
return 0;
}