Picking about random character without repetition c++ - c++

I need to pick m amount of random characters(letters) without repetition and im completely stuck, i keep getting only 1 random letter. How can i fix my code? Is there even a way to fix this or should i just scrap this idea and look for a solution from some kinf od tutorials?
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <string>
using namespace std;
int main()
{
cout << "number below 27" << endl;
int m;
cin >> m;
srand(time(NULL));
bool repeat = false;
char letters[m];
char letter;
for(int i = 0; i < m; i++){
letter = rand()%26 +97;
repeat = true;
for(int j = 0; j < m; j++){
if(letters[m] == letters[j]){
repeat = false;
break;
}
}
if(repeat){
letters[m] = letter;
}
}
for (int i = 0; i < m; i++){
cout << letters[m];
}
}

You can use suffle -
#include <random>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main ()
{
char charSet[]={'a','b','c'};//You can add all the charecters
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(charSet,charSet+3,g);
for(auto c : charSet)
{
std::cout<<c;
}
std::cout<<endl;
return 0;
}

bool repeat = false;
vector<char> letters(m);
char letter;
for(int i = 0; i < m; i++){
do
{
repeat = false;
letter = rand()%26 +97; // generate new random number
for(int j = 0; j<=i; j++) // iterate through the already generated numbers
{
if (letter == letters[j]){ // if the generated number already exists, do the while again
repeat = true;
break;
}
}
} while(repeat);
letters[i] = letter; // assign the unique number
cout << letter;
repeat = false;
}
You repeat the random number generator until you have a unique random number.
And to output your values use i because m is constant and out of bounds:
for (int i = 0; i < m; i++){
cout << letters[i];
}

I think the direct method is to use set in C++. The following solution is done just now utilising set to ensure the unique. Hope it could be helpful.
#include <iostream>
#include <ctime>
#include <set>
#include <random>
using namespace std;
int main()
{
cout << "number below 27" << endl;
int m;
cin >> m;
srand(time(NULL));
set<char> letters_set;
while(letters_set.size() < m){
char c = rand()%26+'a';
letters_set.insert(c);
}
for(auto c: letters_set)
cout<<c<<endl;
}
A more efficient solution which also ensure the equal possibility for each letter.
#include <iostream>
#include <ctime>
#include <set>
#include <random>
using namespace std;
int main()
{
cout << "number below 27" << endl;
int m;
cin >> m;
srand(time(NULL));
vector<int> all_letters(26, 'a');
for(int i = 0; i < 26; ++i) all_letters[i] += i;
vector<char> letters_set;
for(int i = 0; i < m; ++i){
int select = rand()%all_letters.size();
letters_set.push_back(all_letters[select]);
all_letters.erase(all_letters.begin()+select);
}
for(auto c: letters_set)
cout<<c<<endl;
}

There is an obvious error in the logic of your code: when you test for repetition you compare to the beyond the end letter only, instead to all those sampled so far. The correct test would be
for(int i = 0; i < m; i++) {
bool repeating;
char tryletter;
do {
tryletter = rand()%26 +97;
repeating = false;
for(auto j=0; j!=i && !repeating; ++j)
repeating = tryletter == letters[j];
} while(repeating);
letters[i] = tryletter;
}
Though this is not the most efficient way to do what you've been asked to do. A more efficient way would be to start with all 26 letters, pick one at random and remove it from the set, then continue to pick and remove random letters. For example
std::string random_letters_without_repetition(std::size_t m)
{
std::string letters;
std::string all = "abcdefghijklmnopqrstuvwxyz";
assert(m <= all.size());
std::random_device r;
std::default_random_engine rng(r());
while(m--) {
std::uniform_int_distribution<std::size_t> uni{0,all.size()-1};
auto index = uni(rng);
letters += all[index];
all.erase(index);
}
return letters;
}

Related

c++ how print how many element are repeated in 2 array?

I have two arrays and I want to count how many elements are same between two arrays.
I try many times but the output is not correct. The correct should be 6 times
but the output is 4 times in the code.
Note: if s1 is "ss" and s2 is "ss", is the result 2
Here is my code:
#include <iostream>
#include <string>
using namespace std;
int main() {
char s1[] = "FOOBART";
char s2[] = "BFORATO";
int flag=0;
for(int i=0, j=0; i < sizeof(s1) && j < sizeof(s2); ) {
if(s1[i] == s2[j]) {
flag++;
i++;
j++;
} else if(s1[i] < s2[j]) {
i++;
} else {
j++;
}
}
cout << flag;
}
All elements of s1 are present in both strings so the output will be equal to the length of s1. Here is the correct code
#include <iostream>
using namespace std;
int main() {
char s1[] = "FOOBART";
char s2[] = "BFORATO";
int count=0;
for (int i=0; i<sizeof(s1)-1; i++) {
for (int j=0; j<sizeof(s2)-1; j++) {
if (s1[i]==s2[j]) {
count++;
break;
}
}
}
cout<<count<<endl;
}
Hope this will help you
solution using stl algorithms:
#include <iostream>
#include <algorithm>
#include <string>
int main()
{
const std::string s1 = "FOOBART";
std::string s2 = "BFORATO";
int count = 0;
auto beg = begin(s2);
for(auto& elm : s1)
{
auto x = find(beg, end(s2), elm);
if(x != end(s2))
{
*x = *beg;//get rid of elment and reduce the range of search.
++beg;
++count;
}
}
std::cout << count;
return 0;
}

Complexity Reduction to O(n) Over Multiple Simultaeneous Vector Iteration

So I have 2 string vectors with the following content:
tokens: name name place thing thing
u_tokens: name place thing
Now my task is to simultaneously loop through both these vectors and find the occurrence of each word and store it in a third vector. Here's a minimal working implementation that I did (my task doesn't mention about duplicates so I did not consider removing it) :
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<int> counts;
vector<string> tokens;
vector<string> u_tokens;
tokens.push_back("name");
tokens.push_back("name");
tokens.push_back("place");
tokens.push_back("thing");
tokens.push_back("thing");
u_tokens.push_back("name");
u_tokens.push_back("place");
u_tokens.push_back("thing");
string temp;
int temp_count = 0;
for (int i = 0; i < tokens.size(); i++)
{
temp = tokens[i];
for (int j = 0; j < u_tokens.size(); j++)
{
if(temp == u_tokens[j])
{
temp_count++;
}
}
temp = tokens[i];
for (int k = 0; k < tokens.size(); k++)
{
if (temp == tokens[k])
{
temp_count++;
}
}
counts.push_back(temp_count);
temp_count = 0;
}
for (vector<int>::const_iterator i = counts.begin(); i != counts.end(); ++i)
cout << *i << " ";
return 0;
}
However, I noticed, this obviously has a O(n^2) complexity. How can I reduce it to O(n)? Is it possible?
Regards.
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
using namespace std;
void CountOccurences(const vector<string>& input, unordered_map<string, size_t>& occurences)
{
for (int i = 0; i < input.size(); i++)
{
occurences[input[i]]++;
}
}
int main()
{
vector<string> tokens;
vector<string> u_tokens;
unordered_map<string, size_t> occurences;
tokens.push_back("name");
tokens.push_back("name");
tokens.push_back("place");
tokens.push_back("thing");
tokens.push_back("thing");
u_tokens.push_back("name");
u_tokens.push_back("place");
u_tokens.push_back("thing");
CountOccurences(tokens, occurences);
CountOccurences(u_tokens, occurences);
for (auto i : occurences)
cout << i.first << "=" << i.second << " ";
return 0;
}
Use std::unordered_map as O(1) access container to create O(N) solution. In cost of memory of course.
Link to online compiled program

Size of a vector of pairs

I am filling up an adjacency list of vector with pairs given by :
vector<pair<int, int>> adj[1000];
I am doing a depth first search on the list but experiencing some weird behaviour. The first print statement prints some value which means I have some items in adj[s][0], adj[s][1], adj[s][2] and so on. However when I calculate the size of adj[s] in the next line it prints out to be zero. Am I missing something here?. Is my definition for vector of pairs correct?. The adjacency list is correctly filled because when I ran cout << adj[s][0].first << endl; in dfs, it was correctly showing me the neighbors of each and every node.
Complete code
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <utility>
#include <climits>
#include <algorithm>
using namespace std;
vector<pair<int, int>> adj[1000];
bool visited[1000];
int nodeweight[1000];
void initialize()
{
for(int i = 0; i < 1000; i++)
visited[i] = false;
for(int i=0; i < 1000; i++)
adj[i].clear();
for(int i = 0; i <1000; i++)
nodeweight[i] = INT_MAX;
}
void dfs(int s)
{
visited[s] = true;
cout << adj[s][1].first << endl;
int minimum = INT_MAX, tovisit = 0;
for(int i = 0; i < adj[s].size(); i++)
{
cout << adj[s][i].second;
if(!visited[adj[s][i].first] && adj[s][i].second < minimum)
{
minimum = adj[s][i].second;
tovisit = adj[s][i].first;
}
}
nodeweight[tovisit] = minimum;
//dfs(tovisit);
}
int main() {
int N, E;
cin >> N >> E;
while(E--)
{
int i, j, w;
cin >> i >> j >> w;
adj[i].push_back(make_pair(j,w));
adj[j].push_back(make_pair(i,w));
}
initialize();
for(int i = 1; i <= N; i++)
{
dfs(i);
}
return 0;
}
You are clearing adj again after filling in initialize().
First you fill adj in the while loop in main. Then you call initialize() which includes this loop clearing all vectors in it:
for(int i=0; i < 1000; i++)
adj[i].clear();
Then you have cout << adj[s][1].first << endl; in dfs which is undefined behavior because there are no elements in adj[s]. The fact that you seem to get the correct results is just coincidental undefined behavior (although practical it is because the memory holding the vector data was not cleared.)
adj[s].size() is correctly reported as 0.

Displaying 2 iterated arrays in one for loop

I am working on creating a simulation of a test that will
1. randomize multiple choice answers
2. display the choices from a) b) c) d)
I have both codes done separately however can I use on for-loop to go about displaying this? Is this the best way to do this? All help is appreciated thank you!
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main (){
const int TEST_SIZE = 13;
srand(time(0));
string animals[TEST_SIZE] = {"dog","cat","fish","elephant","rhinoceros","cheetah","tiger","lion","zebra","giraffes","alligators","sloths","kangaroos" };
for (int i = 0; i < TEST_SIZE; i++){
//generate random index number (0,1,2,3,4,5...)
int index = rand() % FACE_SIZE;
//swap animals[i] with animals[index]
string temp = animals[i];
animals[i] = animals[index];
animals[index] = temp;
}
//loop through array and print values
for (int i = 0; i < 7; i++){
cout << animals[i] << " ";
}
}
//separate code for part 2: choices from a-g
#include <iostream>
#include <string>
using namespace std;
int main()
{
const int CHOICE_SIZE = 7;
string choices[] = { "a)", "b)","c)","d)","e)","f)","g)" };
for (int i = 0; i < CHOICE_SIZE; i++) {
cout << choices[i] << " ";
}
}
You can iterate over both arrays and stop when smaller will ends
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main (){
const int TEST_SIZE = 13;
srand(time(0));
string animals[TEST_SIZE] = {"dog","cat","fish","elephant","rhinoceros","cheetah","tiger","lion","zebra","giraffes","alligators","sloths","kangaroos" };
for (int i = 0; i < TEST_SIZE; i++){
//generate random index number (0,1,2,3,4,5...)
int index = rand() % FACE_SIZE; // maybe here should be TEST_SIZE?
//swap animals[i] with animals[index]
string temp = animals[i];
animals[i] = animals[index];
animals[index] = temp;
}
//loop through array and print values
for (int i = 0; i < 7; i++){
cout << animals[i] << " ";
}
const int CHOICE_SIZE = 7;
string choices[] = { "a)", "b)","c)","d)","e)","f)","g)" };
for (int i = 0; i < CHOICE_SIZE && i < TEST_SIZE; i++) {
cout << choices[i] << " " << animals[i] << ", ";
}
}
Also, consider that if you want to use fixed-size array, you can use std::array:
#include <array>
std::array<string, TEST_SIZE> animals = {...};
And for shuffling you can use std::shuffle from 'algorithm' header .

Neumann's Random Generator

Please read the task first: http://codeabbey.com/index/task_view/neumanns-random-generator
I have to keep track of the number of iterations, but I get very strange results. In the example after the task we have the numbers 0001 and 4100 and they should come to loop after 2 and 4 iterations. But my results are 1, 4 or if I change the place of the counter 2 or 5 but never 2 and 4. Here is my code:
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
int value;
int counter;
int result;
int setvalue = 1; // use to exit the loop if setvalue == 0;
cin >> n;
vector<int> new_results(0); // use to store all the results from iterations
vector<int> results_vec(0); // use to store the number of iterations for each number
for (int i = 0; i < n ; i++)
{
cin >> value;
while(setvalue == 1)
{
value = value*value;
value = (value % 1000000) / 100;
if(find(results_vec.begin(), results_vec.end(), value) == results_vec.end())
{
results_vec.push_back(value);
}
else
{
counter = results_vec.size();
new_results.push_back(counter);
setvalue = 0;
}
}
results_vec.clear();
}
for (int i = 0; i < new_results.size() ; i++)
{
cout << new_results[i] << " ";
}
}
Going in and out of a string the way you have is really very ugly and extremely expensive computationally.
Use
(value % 1000000) / 100;
instead to extract the middle four digits. This works by (1) taking the modulus to remove the leading two digits then (2) removing the last two with integer division.
As it's so much simpler, I suspect that will fix your bugs too.
Here is the correct code, thank you for all your help.
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
int value;
int counter;
int result;
cin >> n;
vector<int> new_results(0); // use to store all the results from iterations
vector<int> results_vec(0); // use to store the number of iterations for each number
for (int i = 0; i < n ; i++)
{
cin >> value;
results_vec.push_back(value);
while(true)
{
value = value*value;
value = (value % 1000000) / 100;
if(find(results_vec.begin(), results_vec.end(), value) == results_vec.end())
{
results_vec.push_back(value);
}
else
{
counter = results_vec.size();
new_results.push_back(counter);
break;
}
}
results_vec.clear();
}
for (int i = 0; i < new_results.size() ; i++)
{
cout << new_results[i] << " ";
}
}