Non-repeating series of non-repeating numbers

I will try to describe my problem as well as I can, since this is my first time here :)

So, I need to write a C ++ program, which you may or may not guess from the name, prints to display a series of random numbers that are not repeated either in numbers or in the series itself.

I have 4 "slots" to fill in a series of numbers. And numbers can be randomized from 0 to 4 (which cannot be repeated).

What I want to do is:

SLOT 1: 1 3 2 4

SLOT 2: 3 1 4 2 <----- As you can see, they do not repeat horizontally or vertically.

SLOT 3: 2 4 3 1

SLOT 4: 4 2 1 3

This is the code I ran into until I got stuck (it is no secret that the ugly code I know)

    void MC_Slot_Rand()
{
    text.setDefaultColor("white");//don't mind this
    srand((unsigned)time(NULL));
    int n1;
    int n2;
    int n3;
    int n4;
    int number;
    int slotN = 0;
    int slotN_2 = 1;
        while (slotN < dim)
        {
            color.red();//don't mind this
            cout << "SLOT " << slotN_2 << ":  ";
            color.white();//don't mind this either
            n1 = 1;//RESET 
                   //for some reason, if i don't put 1
                   // the program repeats the numbers
            n2, n3, n4 = 10;//RESET
            do
            {
                number = rand() % 4;
            } while (number == n1);
            n1 = number;

            do
            {
                number = rand() % 4;
            } while (number == n1);
            n2 = number;

            do
            {
                number = rand() % 4;
            } while (number == n1 || number == n2);
            n3 = number;

            do
            {
                number = rand() % 4;
            } while (number == n1 || number == n2 || number == n3);
            n4 = number;

            //cout << n1 << n2 << n3 << n4;//debug
            MC_ENUM(n1);
            MC_ENUM(n2);//this function simply takes the number and
                        //transforms it into a letter using a switch statement
                        // example: 0 = A, 1 = B, etcetera...

            MC_ENUM(n3);
            MC_ENUM(n4);
            ut.spacer(3);//this function does cout<<endl; as many times
                         //as the number specifies
            slotN++;
            slotN_2++;

        }

}//END OF FUNCTION

      

What this piece of code does is just print 4 series of non-repeating numbers BUT the numbers are repeated vertically! And of course I don't want that to happen.

I hope that someone more experienced than me can help me :)

Very important: if you want to try this code, cancel the line commented with functions don't mind this

, MC_ENUM();

as well as ut.spacer();

because they are part of my library, and will not work with you: P

Thank you for your time.

+3


source to share


4 answers


Here's what you can do: When you want the numbers to be unique, rather than generate random numbers, you must create an array of all the unique numbers you want. In this case, it is an array of length 4 with values ​​[1,2,3,4]. Now randomly shuffle the array using the well-known good shuffle algorithm that guarantees nearly equal opportunity for all permutations. If you want a certain digit to appear in the same index, you can easily add a rule to the shuffle that requires a unique placement for each shuffled digit.



Here's another approach: this approach is especially good for small lengths. Create all possible permutations and then select an arbitrary permutation. To defend your additional claim, you simply ignore inappropriate substitutions. The clear advantage of this method is that it is completely deterministic.

0


source


As I understand it, you are doing a randomized vector of all permutations of numbers 1-4.

Fortunately, the answer is in the standard library:

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

using namespace std;

bool column_match(const vector<int>& v1, const vector<int>& v2)
{
    auto N = std::min(v1.size(), v2.size());
    for (size_t i = 0 ; i < N ; ++i) {
        if (v1[i] == v2[i])
            return true;
    }
    return false;
}

int main()
{
    vector<int> nums = { 1, 2, 3, 4 };

    vector<vector<int>> series;
    do {
        series.push_back(nums);
    } while (next_permutation(begin(nums), end(nums)));

    random_shuffle(begin(series), end(series));

    vector<vector<int>> result;
    copy_if(begin(series), end(series), back_inserter(result), [&](const auto& candidate){
        return !any_of(begin(result), end(result), [&](const auto& check){
            return column_match(candidate, check);
        });
    });

    for (const auto& s : result) {
        copy(begin(s), end(s), ostream_iterator<int>(cout, ","));
        cout << endl;
    }

    return 0;
}

      



Output example:

4,3,1,2,
3,2,4,1,
1,4,2,3,
2,1,3,4,
Program ended with exit code: 0

      

0


source


I think you do that, and that's my point.

go ahead, you have to define arry as [4] [4], when it produces a number where you store the number in arry, then the next numbet is created, compare it with the others in that line horizontally if it repeats and do the next if no and save it

when the first line is executed, in the second line, when multiplying the number, you not only compare it with this line horizontally, but also with other lines vertically

like this line by line, you will do it.

0


source


You can cheat. You already have one solution to your question:

1 3 2 4
3 1 4 2
2 4 3 1
4 2 1 3

      

You can use this solution to generate others. First convert this solution to letters:

A C B D
C A D B
B D C A
D B A C

      

Second, choose a random mapping of four letters, A, B, C, D to four digits, 1, 2, 3, 4. Replace the letters in your grid with the corresponding number from your mapping. This will give a solution.

For further possible solutions, you can swap columns in your grid, or swap rows in your grid, although some of the resulting grids may be disabled. If you do this, you will need to check things more thoroughly.

0


source







All Articles