Random string from vector C++ [closed] - c++

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I have a question about this code. I got what I was expecting but I don't understand why sometimes I get the result and sometimes not.
In this case, the output suppose to show the word "dive" every time I run the code but sometimes the output is not giving me any value.
Is it because the if statement? How can I get always the result("dive") and not sometimes?
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
using namespace std;
int main()
{
srand(time(NULL));
vector <string> Words = {"dive", "friends", "laptop"};
string n_words = Words[rand() % Words.size()];
for(int i = 0; i < 1; i++)
{
if(n_words.length() <= 4)
{
cout << n_words << endl;
}
}
}
EDIT ANOTHER EXAMPLE:
I would like to pick up a random word not longer than 4 letters from a list of words with differents lengths. When I run my code sometimes I get "dive" sometimes "lego" and sometimes nothing. Is there any way to get always some of this two values ?
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
using namespace std;
int main()
{
srand(time(NULL));
vector <string> Words = {"dive", "table", "laptop", "lego", "friends"}
string n_words = Words[rand() % Words.size()];
for(int i = 0; i < 1; i++)
{
if(n_words.length() <= 4)
{
cout << n_words << endl;
}
}
}

Personally I would copy to a secondary temporary vector, shuffle it, and get the first element of that vector.
And I would have put it in a separate function.
In code something like this perhaps:
std::string select_random_short_word(std::vector<std::string> const& long_words)
{
// Create a vector and copy all "short" words to it
std::vector<std::string> short_words;
std::copy_if(begin(long_words), end(long_words), std::back_inserter(short_words),
[](std::string const& w) { return w.length() <= 4; });
// Make sure there are any short words
if (short_words.size() == 0)
{
return ""; // Nope, no short words
}
// Randomly shuffle the short words
std::random_device device;
std::default_random_engine engine(device());
std::shuffle(begin(short_words), end(short_words), engine);
// Return a random short word
return short_words[0];
}
This will reduce your main function to simply:
int main()
{
std::vector<std::string> words = {"dive", "table", "laptop", "lego", "friends"};
std::cout << select_random_short_word(words) << '\n';
}

Related

Trying to add elements to a Vector classified with a Struct

I'm making a program to basically show the statistics about words the user enters. The rest of the program is fine so far, but I'm having a hard time adding words to a vector of type WordCount.
I have looked around and found several answers, which I would've thought could solve my issue, but I either get a very weird compiler error or it just does not work. I have tried using emplace_back and push_back with calls I thought was right. In essence, my problem code is as follows:
#include <iostream>
#include <string>
#include <vector>
using namespace std; //for simplicity here
struct WordCount {
string word;
int count;
//I have tried using this too:
WordCount(string _word, int _count) : word{_word}, count{_count} {}
};
//...//
void wordToVector(/**...**/,string addStr, vector<WordCount>& wordStats){
/**... code that I've tested to work; basically determined if the
word was already said as I need to have unique words only...**/
wordStats.push_back(WordCount(addStr, 1));
/** also tried: (some had "#include <istream>" when using emplace_back
but that didn't seem to make a difference for me in any case)
wordStats.emplace_back(WordCount(addStr, 1));
wordStats.emplace_back({addStr, 1});
wordStats.push_back(addStr, 1)
wordStats.push_back(addStr).word; (and wordStats.push_back(1).count;)
**/
}
int main() {
vector<WordCount> wordStats(1); //"1" to initialize the size
wordStats.at(0).word = "";
wordStats.at(0).count = 0;
/**There's already a part to change the first values to what they should
be, and it worked last I tested it. Below is a part was for my
personal use to see if anything came out... if it worked**/
for (int i = 0; i < 3; i++) {
cout << wordStats.at(i).word << endl;
cout << wordStats.at(i).count << endl;
}
return 0;
}
I must use a vector for this and cannot use pointers (as I've seen suggested) or #include <algorithm> per the instructions. If I typed in "Oh happy day!", it should be able to print (when fixed, with the current cout statements):
OH
1
HAPPY
1
DAY
1
(There's an earlier part that capitalizes every letter, which I tested to work).
This is my first post here because I'm lost. Please let me know if I provided too much or not enough. **Edited formatting
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct WordCount {
string word;
int count;
};
void wordToVector(string addStr, vector<WordCount>& wordStats){
for (int i = 0; i < wordStats.size(); i++) {
if (wordStats[i].word == addStr) {
wordStats[i].count = wordStats[i].count + 1;
return;
}
}
struct WordCount wc;
wc.word = addStr;
wc.count = 1;
wordStats.push_back(wc);
}
int main() {
vector<WordCount> wordStats;
wordToVector("hehe", wordStats);
wordToVector("hehe", wordStats);
wordToVector("haha", wordStats);
for (int i = 0; i < wordStats.size(); i++) {
cout << wordStats.at(i).word << endl;
cout << wordStats.at(i).count << endl;
}
return 0;
}
Using this code I get output:
hehe
2
haha
1
Is there anything else that needs to be added?
If you want to split the input by the spaces and check for occurrences of every word in the input it could be quite inefficient for longer texts to check for every word (Would be linear I think with M*N complexity), so if you are allowed I do suggest to use a map with word as key and value as the amount of occurrences - or something in that fashion.

Error when passing function as an argument in C++ [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I encountered this strange thing with with C++ when i tried to pass a function as an argument to another one. the problem here is that it works but not giving me the expected result.
here's my code (msvc2013):
#include <stdio.h> /* printf, NULL */
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <iostream>
typedef unsigned int uint32_t;
typedef unsigned char uint8_t;
using namespace std;
#include "stdafx.h"
uint32_t random_color()
{
uint8_t r = rand() % 255;
uint8_t g = rand() % 255;
uint8_t b = rand() % 255;
uint32_t rgb = ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b);
return rgb;
}
void print_rgb(uint32_t(*color_generator)() = &random_color)
{
std::cout << color_generator << std::endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
for (int i = 0; i < 5; i++)
{
srand(time(NULL));
print_rgb();
}
system("PAUSE");
return 0;
}
the purpose of this code is more complicated, but this is a minimal example.
Question : although as you see, there was an srand(time(NULL)); in order for rand() to change values, it dosen't !
so , at the 5 times, I got the same value !
Is there any reason for this ? Am I missing something ?
looks like you are printing value of pointer to function, your code should be:
std::cout << color_generator() << std::endl;
Nothing weird is going on. This code prints out the address passed into it, and the address isn't random.
void print_rgb(uint32_t(*color_generator)() = &random_color)
{
std::cout << color_generator << std::endl;
}
You either need to call the function, here or, if your intention was that appending it to the stream would call it, instead implement something similar to a stream manipulator.

Speed of associative array (map) in STL [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
Wrote a simple program to measure the speed of STL. The following code showed that it took 1.49sec on my Corei7-2670QM PC (2.2GHz and turbo 3.1GHz). If I remove the Employees[buf] = i%1000; part in the loop, it only took 0.0132sec. So the hashing part took 1.48sec. Why is it that slow?
#include <string.h>
#include <iostream>
#include <map>
#include <utility>
#include <stdio.h>
#include <sys/time.h>
using namespace std;
extern "C" {
int get(map<string, int> e, char* s){
return e[s];
}
int set(map<string, int> e, char* s, int value) {
e[s] = value;
}
}
double getTS() {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec/1000000.0;
}
int main()
{
map<string, int> Employees;
char buf[10];
int i;
double ts = getTS();
for (i=0; i<1000000; i++) {
sprintf(buf, "%08d", i);
Employees[buf] = i%1000;
}
printf("took %f sec\n", getTS() - ts);
cout << Employees["00001234"] << endl;
return 0;
}
Here's a C++ version of your code. Note that you should obviously take the maps by reference when passing them in get/set.
UPDATE Taking things a bit further and seriously optimizing for the given test case:
Live On Coliru
#include <iostream>
#include <boost/container/flat_map.hpp>
#include <chrono>
using namespace std;
using Map = boost::container::flat_map<string, int>;
int get(Map &e, char *s) { return e[s]; }
int set(Map &e, char *s, int value) { return e[s] = value; }
using Clock = std::chrono::high_resolution_clock;
template <typename F, typename Reso = std::chrono::microseconds, typename... Args>
Reso measure(F&& f, Args&&... args) {
auto since = Clock::now();
std::forward<F>(f)(std::forward<Args>(args)...);
return chrono::duration_cast<Reso>(Clock::now() - since);
}
#include <boost/iterator/iterator_facade.hpp>
using Pair = std::pair<std::string, int>;
struct Gen : boost::iterators::iterator_facade<Gen, Pair, boost::iterators::single_pass_traversal_tag, Pair>
{
int i;
Gen(int i = 0) : i(i) {}
value_type dereference() const {
char buf[10];
std::sprintf(buf, "%08d", i);
return { buf, i%1000 };
}
bool equal(Gen const& o) const { return i==o.i; }
void increment() { ++i; }
};
int main() {
Map Employees;
const auto n = 1000000;
auto elapsed = measure([&] {
Employees.reserve(n);
Employees.insert<Gen>(boost::container::ordered_unique_range, {0}, {n});
});
std::cout << "took " << elapsed.count() / 1000000.0 << " sec\n";
cout << Employees["00001234"] << endl;
}
Prints
took 0.146575 sec
234
Old answer
This just used C++ where appropriate
Live On Coliru
#include <iostream>
#include <map>
#include <chrono>
#include <cstdio>
using namespace std;
int get(map<string, int>& e, char* s){
return e[s];
}
int set(map<string, int>& e, char* s, int value) {
return e[s] = value;
}
using Clock = std::chrono::high_resolution_clock;
template <typename Reso = std::chrono::microseconds>
Reso getElapsed(Clock::time_point const& since) {
return chrono::duration_cast<Reso>(Clock::now() - since);
}
int main()
{
map<string, int> Employees;
std::string buf(10, '\0');
auto ts = Clock::now();
for (int i=0; i<1000000; i++) {
buf.resize(std::sprintf(&buf[0], "%08d", i));
Employees[buf] = i%1000;
}
std::cout << "took " << getElapsed(ts).count()/1000000.0 << " sec\n";
cout << Employees["00001234"] << endl;
}
Prints:
took 0.470009 sec
234
The notion of "slow" depends of course in comparison to what.
I ran your benchmark (using the standard chrono::high_resolution_clock instead of gettimeofday() ) on MSVC2013 with release configuration on an Corei7-920 at 2.67 GHz and find very similar results (1.452 s).
In your code, you do basically 1 millions of:
insertion in the map: Employees\[buf\]
update in the map (copying a new element to exisitng element): = i%1000
SO I tried to understand better where the time is spent:
first, the map needs to store the ordered keys, which is typically implemented with a binary tree. So I tried to use an unordered_map which uses a flatter hash table and gave it a very large bucket size to avoid clisions and rehashing. The result is then 1.198 s.
So roughly 20% of the time (here) is needed for making possibile a sorted access to the map data (i.e. you can iterate through your map using the order of the keys: do you need this ?)
next, playing with the order of insertion can really influence significantly the timing. As Thomas Matthews pointed out in the comments: for benchmarking purpose you should use random order.
then, making only and optimised insertion of data (no search no update) using emplace_hint() brings us to a time of 1.100 s.
So 75% of the time is needed to allocate and insert the data
finally, elaborating on the previous test, if you add an additional search and update after emplace_hint(), then the time goes up slightly above the original time (1.468 s). This confirms that access to the map is only a fraction of the time and most of the execution time is needed for the insertion.
Here the test for the point above:
chrono::high_resolution_clock::time_point ts = chrono::high_resolution_clock::now();
for (i = 0; i<1000000; i++) {
sprintf(buf, "%08d", i);
Employees.emplace_hint(Employees.end(), buf, 0);
Employees[buf] = i % 1000; // matters for 300
}
chrono::high_resolution_clock::time_point te = chrono::high_resolution_clock::now();
cout << "took " << chrono::duration_cast<chrono::milliseconds>(te - ts).count() << " millisecs\n";
Now your benchmark not only depends performance of the map: you do 1 million of sprintf() to set your buffer, and 1 million of conversion to a string. If you'd use a map instead, you'd notice that the whole test would take only 0.950s instead of 1.450s:
30% of your benchmark time is caused not by the map, but by the many strings you handle !
Of course, all this is much slower than a vector. But a vector doesn't sort its elements, and cannot provide for associative store.

c++ program crashing because of if statment [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
My c++ program is crashing i think because of an if statement. I am using MinGW compiler and am given no errors. I have no idea as to why i am getting the error. The if statement in my generate function looks fine to me. Im comparing a string with an instance of a vector string.
here is the cpp code:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
#include "Insultgenerator_0hl14.h"
using namespace std;
FileException::FileException(const string& m) : message(m){}
string& FileException::what(){ return message;}
NumInsultsOutOfBounds::NumInsultsOutOfBounds(const string& m) : message(m){}
string& NumInsultsOutOfBounds::what(){ return message;}
InsultGenerator::InsultGenerator(const InsultGenerator& ) {};
InsultGenerator::InsultGenerator(){};
void InsultGenerator::initialize() {
int cols(0);
srand ( time(NULL));
string words ;
string filename("InsultsSource.txt");
ifstream filetoread(filename.c_str());
if(filetoread.fail()){
throw FileException("File not read.");
}
while(filetoread >> words){
if(cols==0){
colA.push_back(words);
cols++;
} else if(cols==1){
colB.push_back(words);
cols++;
}else{
colC.push_back(words);
cols= cols -2;
}
}
//for (int i=0;i<50;i++){
// cout << " "<< colA[i];
//}
}
string InsultGenerator::talkToMe() const{
string Thou = "Thou";
string a= Thou + " " + colA[(rand()%50)] + " " + colB[rand()%50] + " " + colC[rand()%50] +"!" ;
//cout << a << endl;
return a;
};//end talkToMe
vector<string> InsultGenerator::generate(const int num){
if (num<0){
throw NumInsultsOutOfBounds("You must be insulted at least once");
} else if (num >10000 ){
throw NumInsultsOutOfBounds("You are being insulted too many times!");
}
vector<string> insultList;
string list;
for(int i=0; i<num;i++ ){
list = talkToMe();
if(list != insultList[i]){
//insultList.push_back(list);
//cout << insultList[i]<< endl;
}
}
return insultList;
};//end generate
//int InsultGenerator::generateAndSave(const string filename, const int n) const{
//};//end generateAndSave
int main(){
InsultGenerator ig;
ig.initialize();
ig.talkToMe();
ig.generate(10);
}
Here is the header file :
#ifndef INSULTGENERATOR_0HL14_H_
#define INSULTGENERATOR_0HL14_H_
#include <string>
#include <vector>
using namespace std;
class InsultGenerator{
public:
InsultGenerator();
InsultGenerator(const InsultGenerator&);
void initialize() ;
string talkToMe() const;
vector<string> generate(const int) ;
int generateAndSave (const string, const int) const;
private:
vector<string> colA;
vector<string> colB;
vector<string> colC;
};
class FileException{
public:
FileException(const string&);
string& what();
private:
string message;
};
class NumInsultsOutOfBounds{
public:
NumInsultsOutOfBounds(const string &);
string& what();
private:
string message;
};
#endif
As soon as you call the operator[] on your vector, you are trying to access an element of your vector. In this case the vector is empty, which cause an undefined behaviour.
if(list != insultList[i]){
Before trying to access your vector, make sure that this one is initialized with some values.
The index (i) you are looking for must be lower than the size of the vector insultList.size() (since the indexing start at 0)
You're declaring insultList to be of type vector<string>:
vector<string> insultList;
Then you're trying to access elements of insultList:
if(list == insultList[i]){
//insultList.push_back(list);
//cout << insultList[i]<< endl;
}
But nowhere in between do you actually add anything to insultList -- how many elements does it have? Trying to access insultList[i] refers to unallocated memory which is causing your program crash.

Write a short C++ program that outputs all possible strings formed by using each of the characters ’a’, ’b’, ’c’, ’d’, ’e’, and ’f’ exactly once

I came across this question and I am not able to solve it. All I could code was for small strings like ab,ac,ad,ae,af and such. But not for the longer strings like abc,abcd,etc. It would be really nice if someone could direct me towards some kind of solution. I would prefer without recursion but if not then recursion is also fine.
Here is my code:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<string> make_string(vector<char>vec, char ch)
{
int i=0;
vec.erase(remove(vec.begin(), vec.end(), ch), vec.end());
int size = vec.size();
vector<string>all_strings;
string answer="";
for(i=0;i<size;i++) //here is the "meat". I could add a few more for loops for longer strings
// But I think that would just get messy.
{
answer= answer+ch+vec[i];
all_strings.push_back(answer);
answer="";
}
return all_strings;
}
void print_vector(vector<string>vec)
{
int i=0;
int size = vec.size();
for(i=0;i<size;i++)
{
cout<<vec[i]<<endl;
}
cout<<"--------------------------";
cout<<endl;
}
int main()
{
vector<char>vec;
vec.push_back('a');
vec.push_back('b');
vec.push_back('c');
vec.push_back('d');
vec.push_back('e');
vec.push_back('f');
int i=0;
vector<string>my_strings;
int size=vec.size();
for(i=0;i<size;i++)
{
my_strings=make_string(vec,vec[i]);
print_vector(my_strings);
my_strings.clear();
}
return 0;
}
You are looking for a permutation algorithm. Please take a look at this post on wordaligned.org, which describes an iterative solution to the problem:
Next permutation
The author's code is very simple and makes use of the standard library:
#include <algorithm>
#include <cstdio>
int main()
{
char xs[] = "abcdef"; // <-- modified to fit the question.
do
{
std::puts(xs);
}
while (std::next_permutation(xs, xs + sizeof(xs) - 1));
return 0;
}
If you read further, there is a discussion on the implementation of next_permutation and a breakdown of how it works.