Check String For Consecutive Pairs C++ - c++

I'm looking to write a C++ console app that takes in lines of text from a .txt file, which I have done, now what I need to do is check each line for consecutive pairs of letters
"For example, the word “tooth” has one pair of double letters, and the word “committee” has two pairs of consecutive double letters."
Should I convert each line into a Cstring and loop through each character? I really don't know where to start with this.
I'm not looking for someone to write out the entire solution, I just need to know how to start this.

You could loop through the string from start to the second last char and compare 2 chars at a time. In C++17 you have std::string_view which is handy.
#include <string_view>
size_t pair_count(std::string_view s) {
size_t rv = 0; // the result
for(size_t idx = 0; idx < s.size() - 1; ++idx) {
// compare s[idx] and s[idx+1]
// if they are equal, increase rv by one
// and increase idx by one (if you want "aaa" to count as 1 and not 2)
}
return rv;
}

Related

Get string of characters from a vector of strings where the resulting string is equivalent to the majority of the same chars in the nth pos in strings

I'm reading from a file a series of strings, one for each line.
The strings all have the same length.
File looks like this:
010110011101
111110010100
010000100110
010010001001
010100100011
[...]
Result : 010110000111
I'll need to compare each 1st char of every string to obtain one single string at the end.
If the majority of the nth char in the strings is 1, the result string in that index will be 1, otherwise it's going to be 0 and so on.
For reference, the example I provided should return the value shown in the code block, as the majority of the chars in the first index of all strings is 0, the second one is 1 and so on.
I'm pretty new to C++ as I'm trying to move from Web Development to Software Development.
Also, I tought about making this with vectors, but maybe there is a better way.
Thanks.
First off, you show the result of your example input should be 010110000111 but it should actually be 010110000101 instead, because the 11th column has more 0s than 1s in it.
That being said, what you are asking for is simple. Just put the strings into a std::vector, and then run a loop for each string index, running a second loop through the vector counting the number of 1s and 0s at the current string index, eg:
vector<string> vec;
// fill vec as needed...
string result(12, '\0');
for(size_t i = 0; i < 12; ++i) {
int digits[2]{};
for(const auto &str : vec) {
digits[str[i] - '0']++;
}
result[i] = (digits[1] > digits[0]) ? '1' : '0';
}
// use result as needed...
Online Demo

Program taking too much time

I'm trying to solve a coding problem, the problem is:
Take a string input
Take a number input 'n'
Repeat the string up to n indexes
Count the number of 'a' characters that occur in the repeated string
This problem was authored by tunyash on Hackerrank with title 'Repeated String'
My current solution is taking too much time to run
This is what I am currently doing:
Use a variable to iterate through the original string
Each time the variable exceeds the original string length, reset it to 0
Iterate n times
I've made a function to do the counting as follows:
long long repeatedString(std::string s, long long n) {
long long sIndex{ 0 }, length = s.size(), result{ 0 };
for (long long i = 0; i < n; i++)
{
if (sIndex > (length - 1))
sIndex = 0;
if (s[sIndex] == 'a')
result += 1;
sIndex += 1;
}
return result;
}
I've tried modifying and using binary search algorithm by first writing the whole string then searching but the writing part takes too much time and seems not very intuitive
This is a typical beginner programming exercise. The idea is that you shouldn't blindly overengineer the problem, when a simple mathematical formula is right around the corner. In this case you can simply count the number of a's in the original string and multiply it by n to get the desired result:
std::count(s.begin(), s.end(), 'a') * n
where s is your input string.
Edit: I misinterpreted the question. I assumed n was the number of repetitions of the whole string, whereas it actually was the number of characters to concatenate by modularly concatenating the strings characters up until n number of characters. In this case, simply divide before multiplying: n / s.length() and adjust for the n % s.length() characters remaining with addition. I will leave this as an exercise.

Finding the most(multiple) common word in C++ using unordered_map approach

Find the most common word from a text input, excluding a list of given words. If there are multiple maximum words, display all of them.
My method words for 21/24 test cases, I cannot seem to think of the 3 test cases that I am missing.
I am adding the code that I have right now, which is efficient according to me. I don't want another way of implementing it right now (although suggestions are most welcome), I would just like to pick your brain about the possible test cases I am missing.
vector<string> mostCommonWord(string paragraph, vector<string>& banned) {
unordered_map<string, int>m;
for(int i = 0; i < paragraph.size();){
string s = "";
while(i < paragraph.size() && isalpha(paragraph[i])) s.push_back(tolower(paragraph[i++])); // go through till you find one word completely
while(i < paragraph.size() && !isalpha(paragraph[i])) i++; // avoid all the white spaces and other characters
m[s]++; // include the word found and increment its count
}
for(auto x: banned) m[x] = 0; // make the count of all the banned words to be 0
vector<string> result;
string res = "";
int count = INT_MIN;
// find the maximum count
for(auto x: m)
if(x.second > count) count = x.second;
// we might have the case where all the words were in banned words, which would result the count == -1, so return an empty vector in this case
if(count <= 0) return result;
// add the words corresponding to that to the final vector<string>
for(auto x: m)
if(x.second == count) result.push_back(x.first);
return result;
}
It works for all the scenarios I can think, but fails 3 test cases.
I am not given access to those test cases, would just like to have a discussion of what it could possibly be!
Are you sure in the fact that other chars (digits) should be treated as word delimiters?
If paragraph starts with a whitespace or not an alphabetical char you will insert the empty string into the map: m[""] = 1.

Reversing the positions of words in a string without changing order of special characters in O(1) space limit

During mock interview I come up with this question. Interviewer first ask this question without any space limitations. Then he continued with space-limited version. To be on the same page. In the question a string and container class consist of delimiters are given. This is up to you to decide suitable container class and the language of response. I think sample input and output would be enough to understand what really question is.
Input:
"Reverse#Strings Without%Changing-Delimiters"
Output:
"Delimiters#Changing Without%Strings-Reverse"
Note That: Position of "#", "%"," ","-" is not changed
I came up with the solution below:
string ChangeOrderWithoutSpecial(string s, unordered_set<char> delimiter)
{
stack<string> words; // since last words outs first
queue<char> limiter; // since first delimiter outs first
string response =""; //return value
int index=-1; // index of last delimiter visited
int len=s.length();
for (int i =0 ; i <len;i++)
{
if(delimiter.find(s[i]) != delimiter.end()) // i-th char is a delimiter character
{
string temp=s.substr(index+1,i-index-1);
words.push(temp);
char t =s.at(i);
limiter.push(t);
index=i;
}
// i realized that part after interview under assumption starting with word and no double delimiters ie, each word followed by one delimiter
if(index!=s.length()-1)
{
string temp=s.substr(index+1,s.length()-index-1);//until the end;
cout<<temp<<endl;
words.push(temp);
}
while(!limiter.empty())
{
response+=words.top()+limiter.front();
words.pop();
limiter.pop();
}
response+=words.top();
return response;
}
However I couldnt find a o(1) space solution ? Anyone know how ? I also could not figure out if there are multiple delimiters , that also be appricated. Thank you anyone spend time even reading.
Find the first word and the last word. Rotate the string by length(last_word)-length(first_word): this would put the middle part in the correct position. In the example, that'll produce
ersReverse#Strings Without%Changing-Delimit
Then rotate the first and last part of the string, skipping the middle, by length(first_word):
Delimiters#Strings Without%Changing-Reverse
Repeat this algorithm for the substring between the two outermost delimiters.
"Rotate by m" operation can be performed in O(1) space and O(n) time, where n is the length of the sequence being rotated.
Instead of rotating the string, it can be also solved by successive reversing the string.
Reverse the whole string. This is O(n) operation. In your case the string becomes sretimileD-gnignahC%tuohtiW sgnirtS#esreveR.
Find all words and reverse each of them. This is O(n) operation. String is now equal to Delimiters-Changing%Without Strings#Reverse.
Reverse delimiters. This is O(n) operation. You'll get wanted result: Delimiters#Changing Without%Strings-Reverse.
Each of these operations can be done in place, so the total memory complexity is O(1) and time complexity is O(n).
It is worth noting that with this approach each character will be visited 4 times (first reverse, finding words, reverse word, reverse delimiter), so (in general case) it should be faster than Igor Tandetnik's answer where characters in the middle of the string are visited many times. However, in special case where each word has the same length, Igor's solution will be faster because the first rotate operation won't exists.
Edit:
Reverse delimiters can be done in O(n) without extra memory in the similar way as the standard reverse. Just iterate through delimiters instead of whole set of characters:
Iterate forward until you reach delimiter;
Reverse iterate until you reach delimiter from the back;
Swap the current delimiters;
Continue procedure until your iterators meet.
Here is procedure in C++ which will do this job
void reverseDelimiters(string& s, unordered_set<char>& delimiters)
{
auto i = s.begin(); auto j = s.end() - 1; auto dend = delimiters.end();
while (i < j) {
while (i < j && delimiters.find(*i) == dend) i++;
while (i < j && delimiters.find(*j) == dend) j--;
if (i < j) swap(*i, *j), i++, j--;
}
}

Comparisons of strings with c++

I used to have some code in C++ which stores strings as a series of characters in a character matrix (a string is a row). The classes Character matrix and LogicalVector are provided by Rcpp.h:
LogicalVector unq_mat( CharacterMatrix x ){
int nc = x.ncol() ; // Get the number of columns in the matrix.
LogicalVector out(nc); // Make a logical (bool) vector of the same length.
// For every col in the matrix, assess whether the column contains more than one unique character.
for( int i=0; i < nc; i++ ) {
out[i] = unique( x(_,i) ).size() != 1 ;
}
return out;
}
The logical vector identifies which columns contain more than one unique character. This is then passed back to the R language and used to manipulate a matrix. This is a very R way of thinking of doing this. However I'm interested in developing my thinking in C++, I'd like to write something that achieves the above: So finds out which characters in n strings are not all the same, but preferably using the stl classes like std::string. As a conceptual example given three strings:
A = "Hello", B = "Heleo", C = "Hidey". The code would point out that positions/characters 2,3,4,5 are not one value, but position/character 1 (the 'H') is the same in all strings (i.e. there is only one unique value). I have something below that I thought worked:
std::vector<int> StringsCompare(std::vector<string>& stringVector) {
std::vector<int> informative;
for (int i = 0; i < stringVector[0].size()-1; i++) {
for (int n = 1; n < stringVector.size()-1; n++) {
if (stringVector[n][i] != stringVector[n-1][i]) {
informative.push_back(i);
break;
}
}
}
return informative;
}
It's supposed to go through every character position (0 to size of string-1) with the outer loop, and with the inner loop, see if the character in string n is not the same as the character in string n-1. In cases where the character is all the same, for example the H in my hello example above, this will never be true. For cases where the characters in the strings are different the inter loops if statement will be satisfied, the character position recorded, and the inner loop broken out of. I then get a vector out containing the indicies of the characters in the n strings where the characters are not all identical. However these two functions give me different answers. How else can I go through n strings char by char and check they are not all identical?
Thanks,
Ben.
I expected #doctorlove to provide an answer. I'll enter one here in case he does not.
To iterate through all of the elements of a string or vector by index, you want i from 0 to size()-1. for (int i=0; i<str.size(); i++) stops just short of size, i.e., stops at size()-1. So remove the -1's.
Second, C++ arrays are 0-based, so you must adjust (by adding 1 to the value that is pushed into the vector).
std::vector<int> StringsCompare(std::vector<std::string>& stringVector) {
std::vector<int> informative;
for (int i = 0; i < stringVector[0].size(); i++) {
for (int n = 1; n < stringVector.size(); n++) {
if (stringVector[n][i] != stringVector[n-1][i]) {
informative.push_back(i+1);
break;
}
}
}
return informative;
}
A few things to note about this code:
The function should take a const reference to vector, as the input vector is not modified. Not really a problem here, but for various reasons, it's a good idea to declare unmodified input references as const.
This assumes that all the strings are at least as long as the first. If that doesn't hold, the behavior of the code is undefined. For "production" code, you should include a check for the length prior to extracting the ith element of each string.