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;
}
Related
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];
}
I was given a project in class and almost have it finished, I am required to take a string of numbers and letters and return that string with the numbers printed first followed by the letters in reverse order (ex. abc123 should return 123cba). As of now my code returns a string with the numbers first and the original order of the letters (ex. abc123 returns 123abc). I would be able to do this with two loops however the assignment asks that my code only iterates though the initial string one time. Here is the code I have so far...
#include <iostream>
#include <string>
#include "QueType.h"
#include "StackType.h"
using namespace std;
int main ()
{
QueType<char> myQueue;
StackType<char> myStack;
string myString="hello there123";
char curchar;
string numbers, letters;
for (int i = 0; i < myString.length(); i++) {
if (isdigit(myString.at(i))) {
myQueue.Enqueue(myString.at(i));
myQueue.Dequeue(curchar);
numbers += curchar;
//cout<<numbers<<endl;
}
else if (islower(myString.at(i))) {
myStack.Push(myString.at(i));
curchar = myStack.Peek();
myStack.Pop();
letters += curchar;
//cout<<curchar<<endl;
}
}
cout<<(myString = numbers + letters)<<endl;
}
In my code, I have two .h files that set up a stack and a queue. With the given string, the code loops through the string looking to see if it sees a letter or number. With a number the spot in the string is then saved to a queue, and with a letter it is saved to the stack.
The only other way i can think of reversing the order of the letters is in the if else statement instead of having char = myStack.Peek() every loop, change it to char += myStack.Peek() however I get weird lettering when that happens.
since you already got the string with letters you can basically reverse it and that's it.
//emplace version:
void reverse_str(std::string& in)
{
std::reverse(in.begin(), in.end());
}
//copy version
std::string reverse_str(std::string in)
{
std::reverse(in.begin(), in.end());
return in;
}
in your case the emplace version would be the best match.
in other cases (e.g. when you want to preserve the original string) the copy version is preferred.
adding an example to make it as clean as possible.
int main()
{
std::string inputstr = "123abc";
std::string numbers{};
std::string letters{};
for(auto c : inputstr)
{
if(isdigit(c))
numbers += c;
else
letters += c;
}
reverse_str(letters); //using the emplace version
std::cout << numbers + letters;
}
Here's my take. It only loops through the string once. I don't have your types, so I'm just using the std versions.
std::string output;
output.reserve( myString.size() );
std::stack<char> stack;
for ( char c : myString ) {
if ( std::isdigit( c ) ) // if it's a number, just add it to the output
output.push_back( c );
else // otherwise, add the character to the stack
stack.push( c );
}
// string is done being processed, so use the stack to get the
// other characters in reverse order
while ( !stack.empty() ) {
output.push_back( stack.top() );
stack.pop();
}
std::cout << output;
working example: https://godbolt.org/z/eMazcGsMf
Note: wasn't sure from your description how to handle characters other than letters and numbers, so treated them the same as letters.
One way to do this is as follows:
Version 1
#include <iostream>
#include <string>
int main() {
std::string s = "abc123";
std::string output;
output.resize(s.size());
int i = output.length() - 1;
int j = 0;
for(char &c: s)
{
if(!std::isdigit(c))
{
output.at(i) = c;
--i;
}
else
{
output.at(j) = c;
++j;
}
}
std::cout<<output<<std::endl;
}
You can also use iterators in the above program to obtain the desired result as shown in version 2.
Version 2
#include <iostream>
#include <string>
int main() {
std::string s = "abfsc13423";
std::string output;
output.resize(s.size());
std::string::reverse_iterator iter = output.rbegin();
std::string::iterator begin = output.begin();
for(char &c: s)
{
if(!std::isdigit(c))
{
*iter = c;
++iter;
}
else
{
*begin = c;
++begin;
}
}
std::cout<<output<<std::endl;
}
I am new in c++ and I am trying to solve educational exercise in quiz platform, but in this platform I should use no more than 64 MB of memory. My code use more than 130 MB.
#include <sstream>
#include <string>
#include <fstream>
#include <iterator>
#include <vector>
#include <map>
using namespace std;
template<class Container>
void splitString(const std::string &basicString, Container &cont, char delim = ' ') {
std::stringstream ss(basicString);
std::string token;
while (std::getline(ss, token, delim)) {
cont.push_back(token);
}
}
int main() {
int target = 0;
int count = 0;
std::map<int, int> set;
string line;
ifstream fileR("input.txt");
std::vector<string> c;
if (fileR.is_open()) {
while (getline(fileR, line)) {
if (count == 0) {
target = std::stoi(line);
count++;
continue;
}
splitString(line, c);
for (auto &d : c) {
int key = std::stoi(d);
if (set.count(key)) {
set[key] += 1;
} else {
set[key] = 1;
}
}
c.clear();
}
fileR.clear();
fileR.close();
}
ofstream fileW;
fileW.open("output.txt");
bool found = false;
for (const auto &p : set) {
int d = target - p.first;
if (set.count(d)) {
if (p.first != d || set[d] > 1) {
fileW << 1;
found = true;
break;
}
}
}
if (!found) {
fileW << 0;
}
fileW.close();
return 0;
}
What I can add, remove or change for keep within the coveted 64 MB? I tried free memory manually but no effects. I am not sure that is possible to write more effective algorithm.
Your vector (c) is declared outside the loop and is not cleared every time you call split string. This means every time you pass in a string to split, your vector contains stuff from the previous run. Is this intentional? If it is not, then move your vector into the loop, before you call split string, or clear it in your split string function. If it is intentional please provide more info about what your code is supposed to do.
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.
How to check if two strings have any common part (sub-string) in c++.
I thought of sorting the strings and then using loops on both the strings to check if they have a common part. But I am not sure. And I also thought that this would not be the optimal strategy for the question
Consider strings - 'batman' and 'catman'
They have a common part 'atman'.
P.S. I am not checking for more than one characters. eg - 'apple' and 'batman' have a in common but I am interested in sub-string (min. two common consecutive characters).
This might not be the most efficient code, but so you can get an idea of how it would work in the batman and catman case:
Note: This does solve other cases like "batmanuc" and "catmanic", which would be "atman".
It is not perfect nor the most efficient, but it can help you understand a way to do it and how to manage positions of arrays. From here, implementing it in your own way and adding details is up to you!
like if max>2then print the array, if not, dont print it, for example.
#include <iostream>
using namespace std;
int main()
{
char arr1[10]="batmanuc";
char arr2[10]="catmanic";
char common[10];
int cont=0;
int max=0;
for (int i=0;i<10;i++){
if(arr1[i]==arr2[i]){
if(cont==max){
common[cont]=arr1[i];
cont++;
max++;
}
}
else cont=0;
}
printf("%s",common);
return 0;
}
A stupid algorithm - for each window size from a maximum window (equal to the max of string lengths) to minimum window size (equal to 2, stated in the question), for each position in both strings compare each position with each position in both string with each window_size.
#include <iostream>
#include <string>
#include <cstring>
#include <cassert>
#include <cstdio>
std::string find_common_part(std::string one, std::string two) {
const auto onesize = one.size();
const auto twosize = two.size();
const auto onebegin = one.begin();
const auto twobegin = two.begin();
// min. two common consecutive characters
for (std::size_t window_size = std::max(onesize, twosize);
window_size >= 2;
--window_size) {
for (auto onepos = onebegin,
oneposmax = onebegin + (onesize - window_size);
onepos <= oneposmax;
++onepos) {
for (auto twopos = twobegin,
twoposmax = twobegin + (twosize - window_size);
twopos <= twoposmax;
++twopos) {
if (std::equal(onepos, onepos + window_size, twopos)) {
return std::string(onepos, onepos + window_size);
}
}
}
}
return std::string();
}
int main()
{
std::cout << find_common_part("catman", "batman") << std::endl;
assert(find_common_part("catman", "batman") == "atman");
assert(find_common_part("batman", "manbat") == "man" ||
find_common_part("batman", "manbat") == "bat");
return 0;
}
This function will give you the longest common substring of two strings: (Probably not the fastest way you would do it)
std::string GetLongestCommonSubstring(std::string const& a, std::string const& b) {
std::vector<std::string> substrings;
for (auto beg = a.begin(); beg != std::prev(a.end()); ++beg)
for (auto end = beg; end != a.end(); ++end)
if (b.find(std::string(beg, std::next(end))) != std::string::npos)
substrings.emplace_back(beg, std::next(end));
return *std::max_element(substrings.begin(), substrings.end(),
[](auto& elem1, auto& elem2) { return elem1.length() < elem2.length(); });
}
Example:
int main() {
std::cout << GetLongestCommonSubstring("batman", "catman") << std::endl;
}
Output:
atman