For example: I have a string:
abcdef aaaaaaa bbbbbb
and program should output
abcdef
because it's the word with the greatest number of different letters.
How can I do this?
This is the attempt I made
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void main()
{
string a;
int count = 0;
getline(cin, a);
for (int i = 0; i < a.length(); i++) {
if (a[i] == ' ') {
count++;
}
}
cout << count+1;
}
I think the easiest way to do it is to use std::stringstream to split your string into words.
After that, as already suggested in comments, you could use std::set to count the letters numbers since each element in std::set is unique.
A possible solution would be:
std::pair<std::string, unsigned int> max_letters_word(const std::string & s)
{
std::pair<std::string, unsigned int> result {"", 0};
std::stringstream ss(s);
std::string word;
std::set<char> set;
while(ss >> word)
{
for(char c : word)
set.insert(c);
if(set.size() > result.second)
{
result.first = word;
result.second = set.size();
}
set.clear();
}
return result;
}
And you could use this function as follows:
int main()
{
// Considering this string
std::string s = "abcdef aaaaaaaaa bbbuubbb";
// Call max_letters_word()
std::pair<std::string, unsigned int> result = max_letters_word(s);
// Display the result
std::cout << result.first << ": " << result.second << '\n';
return 0;
}
Live example
With any programming language, "How can I do x?" can have a lot of different answers. Some languages, like python try to lull into the idea that there is one correct (or pythonic as they say) way of doing things, but it's still not true. To python's credit, they usually have a lot less variation than C++ can have.
That is to say, it's a bad question. You need to let us know what your requirements and restrictions are. That allows people to provide solutions that can actually work for you.
Break down the task into sub-tasks. Break the sub-tasks down. Figure out what your algorithm is before writing any code. At a high level, it looks like you need to:
Split the line into individual words
Count the unique characters in each word
Keep track while counting to know which word has the most unique characters
Print the word with the most unique characters
You need to break those tasks down further until you arrive at something you can do. Then do it, and move on. Eventually you'll have a complete program.
If I were to guess, this solution is probably not what you're looking for:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
std::size_t count_unique_chars(std::string word) {
for (auto& i : word) {
i = std::toupper(i);
}
std::sort(word.begin(), word.end());
word.erase(std::unique(word.begin(), word.end()), word.end());
return word.length();
}
int main(int argc, char* argv[]) {
if (argc != 2) return 1;
std::string stringLine = argv[1];
std::stringstream stream(stringLine);
std::vector<std::string> words;
std::copy(std::istream_iterator<std::string>(stream),
std::istream_iterator<std::string>(), std::back_inserter(words));
int maxUniqueChars = 0;
std::string wordWithMostUniqueChars;
for (auto i : words) {
int charCount = count_unique_chars(i);
if (charCount > maxUniqueChars) {
maxUniqueChars = charCount;
wordWithMostUniqueChars = i;
}
}
std::cout << wordWithMostUniqueChars << '\n';
}
Outputs:
❯ ./a.out "abcdef aaaaaaa bbbbbb"
abcdef
❯ ./a.out "cat cattttttt cats"
cats
It works, but this looks like a homework problem and most of that code probably flies right over your head. So it doesn't really help you.
I can make some assumptions, but even they might be off. I'm just trying to highlight how much work goes into asking the right questions. It may sound super-annoying, but there are nothing but benefits. Formulating a "good" question requires you to put in effort. That effort comes across in the asking, and when people get a well-formulated question, they will recognize your effort and be more willing to help. It's also easier to answer a well formulated question.
Here's another program that uses a different tactic.
#include <cctype>
#include <iostream>
#include <string>
#include <vector>
std::size_t count_unique_chars(std::string word) {
std::vector<char> letters(26, 0);
for (auto i : word) {
char c = std::toupper(i);
++letters[c - 'A'];
}
int count = 0;
for (auto i : letters) {
if (i > 0) ++count;
}
return count;
}
int main(int argc, char* argv[]) {
if (argc != 2) return 1;
std::string stringLine = argv[1];
std::vector<std::string> words;
while (stringLine.size() > 0) {
std::size_t idx = stringLine.find_last_of(" ");
std::string word = stringLine.substr(idx + 1);
words.push_back(word);
if (idx == std::string::npos) idx = 0;
stringLine.erase(idx);
}
std::size_t maxUniqueChars = 0;
std::string wordWithMostUniqueChars;
for (auto i : words) {
std::size_t count = count_unique_chars(i);
if (count > maxUniqueChars) {
maxUniqueChars = count;
wordWithMostUniqueChars = i;
}
}
std::cout << wordWithMostUniqueChars << '\n';
}
It still relies on taking advantage of std::string and what it offers, which might not fit with your restrictions.
Both programs follow the high-level steps outlined above. Both programs work, but go about executing the algorithm in different ways. Having clear requirements, and knowing what restrictions are in place will also steer you toward a solution.
Yeah we can do this.. Following is the code which can help you out.
#include<bits/stdc++.h>
using namespace std;
int main(){
string s;
getline(cin,s);
s=s+' ';
string word="";
int ans=0;
map<int,string> mp;
for(int i=0;i<s.length();i++){
char ch=s[i];
if(s[i]!=' ')
word=word+ch;
else{
int c=0;
for(int j=0;j<word.length()-1;j++){
if(word[j]!=word[j+1])
c++;
}
ans=max(ans,c);
mp[c]=word;
word="";
}
}
cout<<mp[ans];
}
Related
Here is my approach where I have tried to split the string into words and then move forward but this is not working.
For instance, the input is: hey hi Mark hi mark
Then the output should be:
hey-1
hi-2
Mark-1
hi-2
mark-1
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<vector<string> > strs;
string str;
cout<<"Enter your strings"<<endl;
getline(cin, str);
int len=str.length();
int j=0;
string s="";
for(int i=0; i<len; i++){
s+=str[i];
if(str[i+1]==' ' || i+1==len){
strs[0][j]=s;
s="";
j++;
i++;
}
}
strs[0][j]="NULL";
int freq;
vector<int> frequency;
for(int n=0; strs[0][n]!="NULL" ;n++){
freq=1;
for(int m=0; strs[0][m]!="NULL"; m++){
if(strs[0][n]==strs[0][m]){
freq++;
}
frequency.push_back(freq);
}
}
for(int x=0; strs[0][x]!="NULL"; x++){
cout<<strs[0][x]<<" - "<<frequency[x]<<endl;
}
return 0;
}
In your code, you have tried to access string elements via its index, which sometimes raises segmentation fault. To solve your problem, I came up with below mention solution.
#include <iostream>
#include <string>
#include <map>
/* getWordFrequency : function with return type std::map<std::string, int>
Param1: Input string
Param2: Default delimiter as " "(void space).
*/
std::map<std::string, int> getWordFrequency(const char *input_string, char c = ' ')
{
// Container to store output result
std::map<std::string, int> result;
// Iteration loop
do{
// Iteration pointer to iterate Character by Character
const char *begin = input_string;
// Continue loop until delimeter or pointer to self detects
while(*input_string != c && *input_string){
// Jump to next character
input_string++;
}
// Iterator for output result container
std::map<std::string, int>::iterator finder = result.find(std::string(begin, input_string));
// Find element using iterator
if(finder != result.end()){
// Element already present in resultunt map then increment frequency by one
finder->second += 1;
} else {
// If no element found then insert new word with frequency 1
result.insert(std::pair<std::string, int>(std::string(begin, input_string),1));
}
} while (0 != *input_string++); // Continue till end of string
return result;
}
int main()
{
// Your string
std::string input_string = "hey hi Mark hi mark";
// Container to catch result
std::map<std::string, int> frequency = getWordFrequency(input_string.c_str());
// Printing frequency of each word present in string
for (auto element : frequency){
std::cout << element.first << "-" << element.second << std::endl;
}
return 0;
}
So, I think your approach using 2 std::vectors is unfortunately wrong. You do not fully understand the difference between char and std::string.
You need to learn abaout that.
There is a more or less standard approach for counting something in a container, like a string or in general.
We can use an associative container like a std::map or a std::unordered_map. And here we associate a "key", in this case the "word" to count, with a value, in this case the count of the specific word.
And luckily the maps have a very nice index operator[]. This will look for the given key and, if found, return a reference to the value. If not found, then it will create a new entry with the key and return a reference to the new entry. So, in both cases, we will get a reference to the value used for counting. And then we can simply write:
std::map<std::string, int> counter{};
counter[word]++;
And that's it. More is not necessary. Please see:
#include <iostream>
#include <string>
#include <sstream>
#include <unordered_map>
int main() {
// Our test String
std::string text{"hey hi Mark hi mark"};
// Here, we will store the result of the counting
std::unordered_map<std::string, unsigned int> counter;
// Now count all words. This one line does all the counting
for (std::istringstream iss{text}; iss >> text; counter[text]++);
// Show result to user
for (const auto& [word, count] : counter) std::cout << word << '-' << count << ' ';
}
It seems also that splitting a string is some how difficult for you. Also here are many many ppossible solutions available.
One of the more sophisticated and more advanced solution is to use the std::sregex_token_iterator. With that you can easily iterate over patterns (described by a std::regex) in a string.
The final code will look nearly the same, but the result will be better, since for example punctuation can be excluded.
Example:
#include <iostream>
#include <string>
#include <unordered_map>
#include <regex>
#include <iterator>
using Iter = std::sregex_token_iterator;
const std::regex re{R"(\w+)"};
int main() {
// Our test String
std::string text{"hey hi Mark, hi mark."};
// Here, we will store the result of the counting
std::unordered_map<std::string, unsigned int> counter;
// Now count all words. This one line does all the counting
for (Iter word(text.begin(), text.end(), re); word != Iter(); counter[*word++]++);
// Show result to user
for (const auto& [word, count] : counter) std::cout << word << '-' << count << ' ';
}
I'm having a problem filling a special array of strings in an automated way.
The strings must be as follows: "01", "012", etc. until you get to "012...XYZ".
I had thought of making a "reference" string like this: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" to be able to browse it and create the other strings based on it but I think there are simpler ways and I can't manage to implement this system.
Thanks in advance!
Just browse the reference string and create the substrings. For that, using std::string::substr is rather useful.
Difficult to get an easier solution.
#include <iostream>
#include <vector>
#include <string>
std::vector<std::string> get_subs(const std::string &ref) {
int n = ref.size();
std::vector<std::string> vec;
for (int i = 2; i <= n; ++i) {
vec.emplace_back (ref.substr(0, i));
}
return vec;
}
int main () {
std::string ref = "01234567";
std::vector<std::string> res = get_subs (ref);
for (std::string &s: res) {
std::cout << s << " ";
}
std::cout << "\n";
}
I am a beginner at coding, and was trying this question that replaces all repetitions of a letter in a string with a hyphen: i.e ABCDAKEA will become ABCD-KE-.I used the switch loop and it works, but i want to make it shorter and maybe use recursion to make it more effective. Any ideas?
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
char x[100];
int count[26]={0}; //initialised to zero
cout<<"Enter string: ";
cin>>x;
for(int i=0; i<strlen(x); i++)
{
switch(x[i])
{
case 'a':
{
if((count[0]++)>1)
x[i]='-';
}
case 'b':
{
if((count[1]++)>1)
x[i]='-';
}
case 'c':
{
if((count[2]++)>1)
x[i]='-';
}
//....and so on for all alphabets, ik not the cutest//
}
}
Iterate through the array skipping whitespace, and put characters you've never encountered before in std::set, if you find them again you put them in a duplicates std::set if you'd like to keep track of how many duplicates there are, otherwise change the value of the original string at that location to a hyphen.
#include <iostream>
#include <string>
#include <cctype>
#include <set>
int main() {
std::string s("Hello world");
std::set<char> characters;
std::set<char> duplicates;
for (std::string::size_type pos = 0; pos < s.size(); pos++) {
char c = s[pos];
// std::isspace() accepts an int, so cast c to an int
if (!std::isspace(static_cast<int>(c))) {
if (characters.count(c) == 0) {
characters.insert(c);
} else {
duplicates.insert(c);
s[pos] = '-';
}
}
}
return 0;
}
Naive (inefficient) but simple approach, requires at least C++11.
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
std::string f(std::string s)
{
auto first{s.begin()};
const auto last{s.end()};
while (first != last)
{
auto next{first + 1};
if (std::isalpha(static_cast<unsigned char>(*first)))
std::replace(next, last, *first, '-');
first = next;
}
return s;
}
int main()
{
const std::string input{"ABCDBEFKAJHLB"};
std::cout << f(input) << '\n';
return 0;
}
First, notice English capital letters in ASCII table fall in this range 65-90. Casting a capital letter static_cast<int>('A') will yield an integer. If after casing the number is between 65-90, we know it is a capital letter. For small letters, the range is 97-122. Otherwise the character is not a letter basically.
Check create an array or a vector of bool and track the repetitive letters. Simple approach is
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string str("ABCDAKEAK");
vector<bool> vec(26,false);
for(int i(0); i < str.size(); ++i){
if( !vec[static_cast<int>(str[i]) - 65] ){
cout << str[i];
vec[static_cast<int>(str[i]) - 65] = true;
}else{
cout << "-";
}
}
cout << endl;
return 0;
}
Note: I assume the input solely letters and they are capital. The idea is centered around tracking via bool.
When you assume input charactor encode is UTF-8, you can refactor like below:
#include <iostream>
#include <string>
#include <optional>
#include <utility>
std::optional<std::size_t> char_to_index(char u8char){
if (u8'a' <= u8char && u8char <= u8'z'){
return u8char - u8'a';
}
else if (u8'A' <= u8char && u8char <= u8'A'){
return u8char - u8'A';
}
else {
return std::nullopt;
}
}
std::string repalce_mutiple_occurence(std::string u8input, char u8char)
{
bool already_found[26] = {};
for(char& c : u8input){
if (const auto index = char_to_index(c); index && std::exchange(already_found[*index], true)){
c = u8char;
}
}
return u8input;
}
int main(){
std::string input;
std::getline(std::cin, input);
std::cout << repalce_mutiple_occurence(input, u8'-');
}
https://wandbox.org/permlink/UnVJHWH9UwlgT7KB
note: On C++20, you should use char8_t instead of using char.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
Here is my code:
#include <iostream>
#include <string>
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
while(n--)
{
string str;
char a[] = {'a','e','i','o','u','A','E','I','O','U'};
getline(cin, str);
for(int i=0 ;i<str.length(); i++)
{
for(int j=0; j<10; j++)
{
if(str[i]==a[j])
{
cout << str[i];
}
}
}
cout << "\n";
}
return 0;
}
Test cases are :
HmlMqPhBfaVokhR
wdTSFuI
IvfHOSNv
I am not removing anything but I am printing only vowels. But, some test cases didn't pass. Maybe this code doesn't work on multiple test cases.
Try this for proper console in :
int main()
{
int n;
std::cin >> n;
std::cin.ignore(); // fix
/* remaining code */
return 0;
}
> To find the vowels in a string
On way of finding the vowels in a string is using a std::binary_search each character of the given string in a vowel table.
Make a sorted array of char s of all vowels(i.e. vowels array).
For each char of the input string, std::binary_search in the
vowels array.
If std::binary_search returns true(meaning the char is an vowel), print the char of the string.
Following is the example code! (See live online)
#include <iostream>
#include <string>
#include <algorithm> // std::for_each, std::binary_search, std::sort
#include <array> // std::array
int main()
{
std::array<char, 10> a{ 'a','e','i','o','u','A','E','I','O','U' };
std::sort(a.begin(), a.end()); // need sorted array for std::binary_search
const std::string str{ "HmlMqPhBfaVokhR wdTSFuI IvfHOSNv" };
std::for_each(str.cbegin(), str.cend(), [&](const char str_char)
{
if (std::binary_search(a.cbegin(), a.cend(), str_char))
std::cout << str_char << " ";
});
return 0;
}
Output:
a o u I I O
> To remove the vowels from a string
Use erase-remove idiom as follows(till c++17†).
Make a sorted array of char s of all vowels(i.e. vowels array).
Using std::remove_if, collect the iterators pointing to the characters, which are vowels. A lambda function can be used as the predicate for std::remove_if, where the std::binary_search is used to check the char in the string exists in the vowels array.
Using std::string::erase, erase all the collected characters(i.e. vowels) from the string.
Following is an example code! (See live online)
#include <iostream>
#include <string>
#include <algorithm> // std::sort, std::binary_search, std::remove_if
#include <array> // std::array
int main()
{
std::array<char, 10> a{ 'a','e','i','o','u','A','E','I','O','U' };
std::sort(a.begin(), a.end()); // need sorted array for std::binary_search
std::string str{ "Hello World" };
// lambda(predicate) to check the `char` in the string exist in vowels array
const auto predicate = [&a](const char str_char) -> bool {
return std::binary_search(a.cbegin(), a.cend(), str_char);
};
// collect the vowels
const auto vowelsToRemove = std::remove_if(str.begin(), str.end(), predicate);
// erase the collected vowels using std::string::erase
str.erase(vowelsToRemove, str.end());
std::cout << str << "\n";
return 0;
}
Output:
Hll Wrld
† Since c++20, one can use std::erase_if for this, which would be less error prone than the the above one. (See online live using GCC 9.2)
#include <iostream>
#include <string> // std::string, std::erase_if
#include <array> // std::array
int main()
{
std::array<char, 10> a{ 'a','e','i','o','u','A','E','I','O','U' };
std::sort(a.begin(), a.end()); // need sorted array for std::binary_search
std::string str{ "Hello World" };
// lambda(predicate) to check the `char` in the string exist in vowels array
const auto predicate = [&a](const char str_char) -> bool {
return std::binary_search(a.cbegin(), a.cend(), str_char);
};
std::erase_if(str, predicate); // simply erase
std::cout << str << "\n";
return 0;
}
> To remove the consonants from a string
To remove the consonants from the given string, in the above predicate negate the result of std::binary_search. (See live online)
const auto predicate = [&a](const char str_char) -> bool {
return !std::binary_search(a.cbegin(), a.cend(), str_char);
// ^^ --> negate the return
};
As side notes,
Avoid the #include<bits/stdc++.h> Read more: Why should I not #include <bits/stdc++.h>?
Do not practice with using namespace std; Read more: Why is "using namespace std;" considered bad practice?
Apart from the std::getline problem already answered:
for(int i=0 ;i<str.length(); i++)
{
for(int j=0; j<10; j++)
{
if(str[i] == a[j])
{
// this is the one you do NOT want to print...
// cout<<str[i];
// skip instead:
goto SKIP;
}
}
std::cout << str[i]; // output the one NOT skipped...
SKIP: (void)0;
}
OK, don't want to start any discussion about usage of goto, there are many ways to avoid it, e. g. by packing the inner for loop into a separate (inline) function. You can have it easier, though, as there already exists such a function; code gets even easier with a range-based for loop:
for(auto c : str)
{
if(!strchr("aeiouAEIOU", c))
{
std::cout << c;
}
}
strchr (from cstring) returns a pointer to the first character in the string equal to the reference character - or nullptr if not found...
To really remove the vowels from the string in a modern C++ way, consider this:
str.erase(std::remove_if(
str.begin(), str.end(),
[](char c) { return strchr("aeiouAEIOU", c) != nullptr; }
), str.end());
Your code probably should looks like (please see comments inline):
#include <iostream>
#include <string>
using namespace std;
int main() {
string vowels = "aeiouAEIOU";
int n;
cin>>n; // assume this stands for line count
while(n-- >= 0)
{
string str, result;
getline(cin, str);
for(int i=0 ;i<str.length(); i++)
{
if (vowels.find(str[i]) != std::string::npos)
result += str[i]; // add character to result if it is not consonant
}
cout<<result<<"\n"; // print result
}
return 0;
}
So I was given the question:
Find ALL of the non-repeating characters in a given string;
After doing some Google searching it was clear to me that finding the first non repeating character was pretty common. I found many examples of how to do that, but I have not really found anything on how to find ALL of the non repeating characters instead of just the first one.
my example code so far is:
#include <iostream>
#include <unordered_map>
using namespace std;
char findAllNonRepeating(const string& s) {
unordered_map<char, int> m;
for (unsigned i = 0; i < s.length(); ++i) {
char c = tolower(s[i]);
if (m.find(c) == m.end())
m[c] = 1;
else
++m[c];
}
auto best = m.begin();
for (auto it = m.begin(); it != m.end(); ++it)
if (it->second <= best->second)
best = it;
return (best->first);
}
int main()
{
cout << findAllNonRepeating("dontknowwhattochangetofindallnonrepeatingcharacters") << endl;
}
I am not sure what I need to change or add to have this find all of the non repeating characters.
k, f, p, s should be the non repeating characters in this string.
Any hints or ideas are greatly appreciated!
As suggested, simply keep a frequency map. Then, once the string is processed, iterate over the map, returning only those values that occur exactly once.
#include <iostream>
#include <map>
#include <vector>
using namespace std;
std::vector<char> nonRepeating(const std::string& s)
{
std::map<char, int> frequency;
for(int i=0;i<s.size();i++)
{
frequency[s[i]]++;
}
std::vector<char> out;
for(auto it = frequency.begin(); it != frequency.end(); it++)
{
if(it->second == 1)
out.push_back(it->first);
}
return out;
}
int main() {
// your code goes here
std::string str = "LoremIpsum";
for(char c : nonRepeating(str))
{
std::cout << c << std::endl;
}
return 0;
}