0

I'm trying to make a 5x10 matrix with full of random letters and once the letter is used, it shouldn't be used again. 25 of them have to be small letters, 25 ought to be big letters. Even numbered columns should be small letters too. I don't know how to avoid using same letters. I tried to send the letters used to another array made of one dimension, then check every letter sent by it so that same letter won't be used but my coding skills didn't let me do it. So, my code is this so far:

#include <iostream> 
#include <iomanip> 
#include <stdlib.h>
#include <ctime>                
#include <locale.h>             


using namespace std;

const int row = 5;
const int column = 10;

int main()  
{
    char matris[row][column];

    srand(time(0));

    for (int i = 0; i < row; i++)
        for (int j = 0; j < column; j++)
            if(j % 2 == 0)
                matris[i][j] = rand() % 25 + 65;
            else
                matris[i][j] = rand() % 25 + 97;
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < column; j++)
            cout << setw(5) << matris[i][j];
        cout << endl;
    }
    system("pause");

    return 0;
    }

So, how can I avoid using same letters? Did I approach wrongly? Is there a easier way to do what I'm trying to do? Thanks...

muadgra
  • 61
  • 5
  • You'll have to be a bit more precise with your question, because "doesn't work" is not a sufficient description. However, the actual skill that you need it to step through the code with a debugger. You can execute it in single steps and inspect the current state of variables, so after every step you could verify whether the state is as you excpect it to be, which will unveil the error pretty fast. – Ulrich Eckhardt Nov 11 '18 at 09:56
  • Create a static array of all possible letters. You can split it into small and big if you have some special demands as to where each of them have to be. Then apply a random permutation to the array (or both if you split it) and you have randomly sorted letters you can use to simply fill your matrix with. – Qubit Nov 11 '18 at 10:00
  • This might be interesting: [How to Generate a Sequence of Unique Random Integers](https://preshing.com/20121224/how-to-generate-a-sequence-of-unique-random-integers/) – Pezo Nov 11 '18 at 10:00
  • To clarify, even columns (i.e. 2, 4, 6... should be small) and odd (1, 3, 5...) should be big? Assuming 1-based indexing. – Qubit Nov 11 '18 at 10:14
  • Yes. That's why I used if declaration. – muadgra Nov 11 '18 at 10:20

2 Answers2

1

A possible solution is to create a vector containing all the symbols you want to use, randomized it, then draw from that. Example

#include <iostream>
#include <algorithm>
#include <vector>
#include <random>

using namespace std;

struct CharPool
{
    size_t pos;
    vector<char> m_unused_char;

    CharPool()
        : pos(0)
    {
        // add whatever characters you like to the pool
        for (char c = 'a'; c <= 'z'; ++c)
            m_unused_char.push_back(c);
        for (char c = 'A'; c <= 'Z'; ++c)
            m_unused_char.push_back(c);

        std::random_device rd;
        std::mt19937 g(rd());

        // randomize
        shuffle(m_unused_char.begin(), m_unused_char.end(), g);
    }

    char next()
    {
        // here we should assert that the pool is not depleted
        return m_unused_char[pos++];
    }
};

int main()
{
    CharPool pool;
    for (size_t i = 0; i < 10; ++i)
        cout << pool.next() << ", ";
    cout << "\n";
}
Fabio
  • 2,105
  • 16
  • 26
0

You need to keep trace of the chars that already appeared, to do so you can use a std::set , at each random call, you check if the random result is inside the set: if it is you simply random another number and retry; if not, you insert it and put it in your matrix.

I'd use a set rather than a vector because it's faster when checking if a value already appears in it.

See this to know how to check if a set contains an element: How to check that an element is in a std::set?

L.C.
  • 1,098
  • 10
  • 21
  • 1
    This is an unnecessary complication in this case. Still, even if one were to go down this road, you only have 52 letters in total, you can create a boolean array and set the values of letters you've already seen to 1. That way no search needs to take place. As for the `set` vs `vector`, the `set` would be faster (asymptotically, it might not be in this special case where the size is so small) because it is sorted. – Qubit Nov 11 '18 at 10:03
  • you're totally right, there are better ways to "keep trace of the chars that already appeared", I gave a solution that is - imho - simple to implement, but definitely not optimal. – L.C. Nov 11 '18 at 10:08