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";
}
Related
#include <iostream>
#include <vector>
#include <unordered_map>
#include <string>
class Solution {
public:
std::vector<std::vector<std::string>> groupAna(std::vector<std::string> strs) {
std::unordered_map<std::string, std::vector<std::string>> ana;
for (int i {0}; i < strs.size(); ++i)
{
std::string key = getKey(strs[i]);
ana[key].push_back(strs[i]);
}
std::vector<std::vector<std::string>> results;
for (auto it = ana.begin(); it != ana.end(); ++it)
{
results.push_back(it->second);
}
// for (int i {0}; i < results.size(); ++i)
// {
// for (int j {0}; j < results[i].size(); ++j)
// {
// std::cout << results[i][j] << " ";
// }
// }
return results;
}
private:
std::string getKey(std::string str) {
std::vector<int> count(26);
for (int i {0}; i < str.length(); ++i)
{
++count[str[i] - 'a'];
}
std::string key {""};
for (int j {0}; j < 26; ++j)
{
key.append(std::to_string(count[j] + 'a'));
}
return key;
}
};
int main() {
std::vector<std::string> strs ({"eat","tea","tan","ate","nat","bat"});
Solution obj;
std::cout << obj.groupAna(strs);
return 0;
}
I receive this error:
Invalid operands to binary expression ('std::ostream' (aka 'basic_ostream<char>') and 'std::vector<std::vector<std::string>>' (aka 'vector<vector<basic_string<char, char_traits<char>, allocator<char>>>>'))
This solution is for Group Anagrams on Leetcode. I'm just using XCode to practice writing out all the code needed, instead of using what Leetcode gives.
My issue comes when calling and trying to print the groupAna() function in class Solution. I believe the error is telling me what I want to print isn't something you can print, but I have no idea if that's entirely correct.
I'm ultimately trying to print each string inside its respective vector. What's commented out was a workaround that gives me what I want, but it doesn't show each word in a vector, so how can I tell if it's in the vector it's suppose to be in, other than it being in the correct order?
Output is bat tan nat eat tea ate
The member function groupAna returns a std::vector<std::vector<std::string>> but there are no operator<< overloads for std::vectors. You could output to a std::ostringstream instead and then return a std::string:
#include <sstream>
class Solution {
public:
// now returns a std::string instead:
std::string groupAna(const std::vector<std::string>& strs) {
std::unordered_map<std::string, std::vector<std::string>> ana;
for (size_t i{0}; i < strs.size(); ++i) {
std::string key = getKey(strs[i]);
ana[key].push_back(strs[i]);
}
std::vector<std::vector<std::string>> results;
for (auto it = ana.begin(); it != ana.end(); ++it) {
results.push_back(it->second);
}
std::ostringstream os; // used to build the output string
for (size_t i{0}; i < results.size(); ++i) {
for (size_t j{0}; j < results[i].size(); ++j) {
os << results[i][j] << ' ';
}
}
/* or using a range based for-loop:
for(const auto& inner : results) {
for(const std::string& str : inner) {
os << str << ' ';
}
}
*/
return os.str(); // return the resulting string
}
// ...
};
Leetcode will ask you to implement a given function, and they will try your code with a battery of unit tests, feeding each test with an input and expecting an output. That is, you don't need to print the vector of vectors of strings within the groupAnagrams function, but just generate that matrix correctly.
Anyway, should you want to test your code, and print the output from groupAnagrams, you could use the fmt library. The <fmt/ranges.h> header lets you print standard containers. In the case of vectors, it will print them enclosed in square brackets. For your example, notice that you will have inner vectors.
[Demo]
#include <fmt/ranges.h>
int main() {
std::vector<std::string> strs({"eat", "tea", "tan", "ate", "nat", "bat"});
Solution obj;
fmt::print("{}", obj.groupAna(strs));
}
// Outputs: [["bat"], ["tan", "nat"], ["eat", "tea", "ate"]]
Or, if you want to flatten that structure, apart from the two solutions proposed by Ted Lyngmo (streams and two nested range-based for loops), you could use C++23 ranges.
[Demo]
#include <fmt/core.h>
#include <ranges>
int main() {
std::vector<std::string> strs({"eat", "tea", "tan", "ate", "nat", "bat"});
Solution obj;
auto&& groups{ obj.groupAna(strs) };
for (auto&& str : (groups | std::views::join)) {
fmt::print("{} ", str);
}
}
// Outputs: bat tan nat eat tea ate
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 am trying to create a function that prints the elements of an array. I set it up so it calculates the size of the array, but I cannot figure why it doesn't work. Can you give me some suggestions?
Thanks!
#include <iostream>
#include <string>
using namespace std;
void print_array(string s){
for(int i = 0; i < ( sizeof(s) / sizeof(s[0]) ); i++){
cout << s[i] << "\n";
}
}
int main()
{
string names[5] = {"Dante", "Greg", "Bob", "Victor", "Saber"};
print_array(names);
}
Welcome to Stack Overflow! Be aware that there are many questions similar to this that have received answers.
As mentioned in a comment, you would need to specify the size of the array if you plan on passing it into a function, because the compiler will look at it not as an array of strings (string s[]), but as a pointer to strings (string s*). Thus, you would need to modify it a little like so:
#include <iostream>
#include <string>
using namespace std;
void print_array(string s[], int size){
for(int i = 0; i < size; i++)
{
cout << s[i] << "\n";
}
}
int main()
{
string names[5] = {"Dante", "Greg", "Bob", "Victor", "Saber"};
print_array(names, sizeof(names) / sizeof(names[0]));
}
You are passing a string instead of an array of strings. You could modify your code by using vectors like this:
void print_array(const std::vector<std::string> &vector){
for (const auto &string : vector) {
std::cout << string << "\n";
}
}
int main()
{
std::vector<std::string> names = {"Dante", "Greg", "Bob", "Victor", "Saber"};
print_array(names);
}
Using vectors allows you to use auto generated for loops, wich are easy to read and use.
im currently setting up the highscore-part for a game and I have a very weird problem because of the weird behaviour of the std::sort function.
Im doing the whole thing in RAD Studio 10.2 (Embarcadero IDE) in C++.
So he is my code:
std::string Line;
int count = 0;
int i = 0;
ifstream File("Highscore.txt");
if(File.is_open())
{
while(getline(File, Line))
{
count += 1;
}
File.close();
}
ifstream ReadFile("Highscore.txt");
if(ReadFile.is_open())
{
string *scores = NULL;
scores = new string[count];
while(getline(ReadFile, Line))
{
scores[i] = Line;
i += 1;
}
ReadFile.close();
std::sort(scores, (scores+count));
UnicodeString Uscores1 = scores[0].c_str();
UnicodeString Uscores2 = scores[1].c_str();
UnicodeString Uscores3 = scores[2].c_str();
UnicodeString Uscores4 = scores[3].c_str();
UnicodeString Uscores5 = scores[4].c_str();
LScore1->Caption = Uscores1;
LScore2->Caption = Uscores2;
LScore3->Caption = Uscores3;
LScore4->Caption = Uscores4;
LScore5->Caption = Uscores5;
}
I get no errors from the compiler/linker and everything work should fine.
The string array gets filled correctly and so on.
But its not sorting.
To show the problem to you I made a screenshot - on the left you can see the txtfile with the scores; on the right you can see the output after the sorting algorithm:
My question now is why this is happening?
Thanks for you help
Welcome to C++. Since you want to list numbers by rank, read them as int not string. Forget about operator new. You will not need it for years, if ever. Use standard containers like std::vector, which take care of the memory allocation and de-allocation transparently.
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
int main() {
using namespace std;
vector<int> scores;
{
ifstream inp("Highscore.txt");
int next;
while (inp >> next) {
scores.push_back(next);
}
}
sort(scores.begin(), scores.end());
for (auto s : scores) {
cout << s << '\n';
}
return 0;
}
How about something like:
int i = 0;
int * scoresInteger = NULL;
scoresInteger = new int[count];
for(i = 0; i < count; i++)
{
scoresInteger[i] = std::stoi(scores[i]);
}
std::sort(scoresInteger, scoresInteger + count);
If you need to, you can convert the integers back into strings using targetStrings[i] = std::to_string(scoresInteger[i]).
string * targetScores = NULL;
targetScores = new std::string[count];
for(i = 0; i < count; i++)
{
targetScores[i] = std::to_string(scoresInteger[i]);
}
delete [] scoresInteger;
scoresInteger = NULL;
Don't forget to delete [] targetScores later.
My question now is why this is happening?
Because your scores are compared as strings and not as ints. Because of that "3" is greater that "25"
std::cout << std::boolalpha << (std::string("3") > std::string("25")) << std::endl; // true
Luckily you can pass a custom comparator (or lambda) to the std::sort to make it behave just as you want:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
const int count = 5;
std::string scores[count] = { "35","25","3","4","5" };
// TWEAKED SORT
std::sort(scores, scores + count, [](std::string const &s1, std::string const &s2)
{
return std::stoi(s2) < std::stoi(s1);
});
// TEST
for (auto const &s : scores)
{
std::cout << s << std::endl;
}
}
The compared strings in the above example are converted to ints and then compared, resulting in the desired sorting order.
35
25
5
4
3
Please note that I do not agree with the rest of your code and I think you should rethink the implementation, as it would be much easier, safer and more efficient to use std::vector<std::string> for your task.
I would like to generate consecutive C++ strings like e.g. in cameras: IMG001, IMG002 etc. being able to indicate the prefix and the string length.
I have found a solution where I can generate random strings from concrete character set: link
But I cannot find the thing I want to achieve.
A possible solution:
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
std::string make_string(const std::string& a_prefix,
size_t a_suffix,
size_t a_max_length)
{
std::ostringstream result;
result << a_prefix <<
std::setfill('0') <<
std::setw(a_max_length - a_prefix.length()) <<
a_suffix;
return result.str();
}
int main()
{
for (size_t i = 0; i < 100; i++)
{
std::cout << make_string("IMG", i, 6) << "\n";
}
return 0;
}
See online demo at http://ideone.com/HZWmtI.
Something like this would work
#include <string>
#include <iomanip>
#include <sstream>
std::string GetNextNumber( int &lastNum )
{
std::stringstream ss;
ss << "IMG";
ss << std::setfill('0') << std::setw(3) << lastNum++;
return ss.str();
}
int main()
{
int x = 1;
std::string s = GetNextNumber( x );
s = GetNextNumber( x );
return 0;
}
You can call GetNextNumber repeatedly with an int reference to generate new image numbers. You can always use sprintf but it won't be the c++ way :)
const int max_size = 7 + 1; // maximum size of the name plus one
char buf[max_size];
for (int i = 0 ; i < 1000; ++i) {
sprintf(buf, "IMG%.04d", i);
printf("The next name is %s\n", buf);
}
char * seq_gen(char * prefix) {
static int counter;
char * result;
sprintf(result, "%s%03d", prefix, counter++);
return result;
}
This would print your prefix with 3 digit padding string. If you want a lengthy string, all you have to do is provide the prefix as much as needed and change the %03d in the above code to whatever length of digit padding you want.
Well, the idea is rather simple. Just store the current number and increment it each time new string is generated. You can implement it to model an iterator to reduce the fluff in using it (you can then use standard algorithms with it). Using Boost.Iterator (it should work with any string type, too):
#include <boost/iterator/iterator_facade.hpp>
#include <sstream>
#include <iomanip>
// can't come up with a better name
template <typename StringT, typename OrdT>
struct ordinal_id_generator : boost::iterator_facade<
ordinal_id_generator<StringT, OrdT>, StringT,
boost::forward_traversal_tag, StringT
> {
ordinal_id_generator(
const StringT& prefix = StringT(),
typename StringT::size_type suffix_length = 5, OrdT initial = 0
) : prefix(prefix), suffix_length(suffix_length), ordinal(initial)
{}
private:
StringT prefix;
typename StringT::size_type suffix_length;
OrdT ordinal;
friend class boost::iterator_core_access;
void increment() {
++ordinal;
}
bool equal(const ordinal_id_generator& other) const {
return (
ordinal == other.ordinal
&& prefix == other.prefix
&& suffix_length == other.suffix_length
);
}
StringT dereference() const {
std::basic_ostringstream<typename StringT::value_type> ss;
ss << prefix << std::setfill('0')
<< std::setw(suffix_length) << ordinal;
return ss.str();
}
};
And example code:
#include <string>
#include <iostream>
#include <iterator>
#include <algorithm>
typedef ordinal_id_generator<std::string, unsigned> generator;
int main() {
std::ostream_iterator<std::string> out(std::cout, "\n");
std::copy_n(generator("IMG"), 5, out);
// can even behave as a range
std::copy(generator("foo", 1, 2), generator("foo", 1, 4), out);
return 0;
}
Take a look at the standard library's string streams. Have an integer that you increment, and insert into the string stream after every increment. To control the string length, there's the concept of fill characters, and the width() member function.
You have many ways of doing that.
The generic one would be to, like the link that you showed, have an array of possible characters. Then after each iteration, you start from right-most character, increment it (that is, change it to the next one in the possible characters list) and if it overflowed, set it to the first one (index 0) and go the one on the left. This is exactly like incrementing a number in base, say 62.
In your specific example, you are better off with creating the string from another string and a number.
If you like *printf, you can write a string with "IMG%04d" and have the parameter go from 0 to whatever.
If you like stringstream, you can similarly do so.
What exactly do you mean by consecutive strings ?
Since you've mentioned that you're using C++ strings, try using the .string::append method.
string str, str2;
str.append("A");
str.append(str2);
Lookup http://www.cplusplus.com/reference/string/string/append/ for more overloaded calls of the append function.
it's pseudo code. you'll understand what i mean :D
int counter = 0, retval;
do
{
char filename[MAX_PATH];
sprintf(filename, "IMG00%d", counter++);
if(retval = CreateFile(...))
//ok, return
}while(!retval);
You have to keep a counter that is increased everytime you get a new name. This counter has to be saved when your application is ends, and loaded when you application starts.
Could be something like this:
class NameGenerator
{
public:
NameGenerator()
: m_counter(0)
{
// Code to load the counter from a file
}
~NameGenerator()
{
// Code to save the counter to a file
}
std::string get_next_name()
{
// Combine your preferred prefix with your counter
// Increase the counter
// Return the string
}
private:
int m_counter;
}
NameGenerator my_name_generator;
Then use it like this:
std::string my_name = my_name_generator.get_next_name();