Search code examples
c++vector

Swap two elements of a vector in a function (C++)


I have to code a program, that takes a word as input. The letters in the input should be mixed around in random order until the initial word is restored.

To check if the initial order is restored, the indices of the letters are printed in front of the sign chain.

e.g. expected output:

[1] 0123 Test

[2] 3201 tsTe

[3] 2103 seTt

and so on.

For that, I defined a String signchain as the initial input and a vector indexes with the numbers 0 to n (length of input word) as elements.

The random rearrangement of the letters is functional, but I am not able to swap the indices in the vector.

In my attached code the functions should be doing the following:

  • mix_cycle: the whole cycle from defining signchain and indexes to stopping the cycle when the initial word is restored
  • form_new_word_by_indexes: rearranging the letters in the word. How many and which letters are swapped should be random. In this function the indices should be swapped according to the swapped letters.
  • getRandomNumber: a random number is generated in a specific interval

My question is: How can I swap the indices according to the letters? I already tried std::swap, but I wasn't able to get it working.

    // a function to choose a random number between two given values
static uint16_t getRandomNumber(uint16_t min, uint16_t max)
{
    uint16_t rand_num = rand() % (max - min) + min;     //Zahl in den gegebenen Grenzen wird generiert
    return rand_num;
}



// the function creates a new word based on the given word and the indices of letters from it
std::string form_new_word_by_indexes(const std::string& initial_word, const std::vector<uint16_t>& indexes)
{
    int min = 0;
    int max = initial_word.length();
    string new_word = initial_word;
    char element_memory;
    uint16_t index_1, index_2;

    for (int i = 0; i <= getRandomNumber(min, max); i++)        //zufällige Anzahl an Tauschvorgängen wird durchgeführt
    {
        while (true) {                                  //kontrolle, damit Zahl nicht mit sich selbst getauscht wird
            index_1 = getRandomNumber(min, max);
            index_2 = getRandomNumber(min, max);
            if (index_1 != index_2)
            {
                break;
            }
        }
        element_memory = new_word[index_1];
        new_word[index_1] = new_word[index_2];
        new_word[index_2] = element_memory;


        swap(indexes[index_1], indexes[index_2]);
    }

    return new_word;
}


// the main loop of the program: randomly rearrange the letters in a given word until we get it
void mix_cycle(const std::string& initial_word)
{
    // number of letters in a word:
    int am_letters = initial_word.length();

    // an array of letter numbers available for permutation, first these are all numbers in order 0, 1, 2, ...
    string signchain = initial_word;

    vector<uint16_t> index_list;
    for (int i = 0; i < am_letters; i++)
    {
        index_list.push_back(i);
    }

    int counter = 0;
    while (true)
    {
        counter += 1;
        cout << "[" << counter << "] ";
        signchain = form_new_word_by_indexes(signchain,index_list);
        for (int i = 0; i < index_list.size(); i++)
        {
            cout << index_list[i];
        }

        cout << " ";

        for (int i = 0; i < am_letters; i++)
        {
            cout << signchain[i];
        }

        
        cout << "\n";
        
    }
    
}

Solution

  • First of all, for the algorithm, if you would like to swap the indices like you are swapping the string, I would just create a string that goes like 012...n naming the indices of the current positions of the letters in the string and swap the places in this string like you swap the letter word.

    To illustrate this, consider the input:

    Test
    

    I would create this index string:

    0123
    

    and if you swap two letters, say the first T and e, the first string will be:

    eTst
    

    now swap the exact same locations in the index string:

    1023
    

    And from there you can have your index string.

    Now, to realize this goal of swapping, you can easily do it manually or use the swap() function, which you have used correctly:

    Manual:

    char temp = str[i]; //i is the indice of one of the locations to be swapped
    str[i] = str[j]; //j is the other indice
    str[j] = temp;
    

    Nonetheless, your problem is that you have to make sure your vectors are not const, because otherwise the swap() won't work because the constant vectors cannot be edited.

    Now, your entire problem seems to be able to be solved with much easier and shorter code. According to the statement, you just need the letters in random order, meaning all permutations instead of just swapped letters. You can achieve this with recursion and a simple map to access the values. In other words, the entire code to create the sequence of all permutations is this:

    #include <iostream>
    #include <vector>
    #include <string>
    #include <unordered_map>
    std::string given;
    std::vector <bool> visited;
    std::unordered_map <char, int> indices;
    void recursion(std::string word) {
        if (word.length() == given.size()) {
            for (char x : word) { std::cout << indices[x]; }
            std::cout << ' ' << word << '\n';
            return;
        }
        for (int i = 0; i < given.size(); i++) {
            if (!visited[i]) {
                visited[i] = true;
                recursion(word + given[i]);
                visited[i] = false;
            }
        }
    }
    int main() {
        std::cin >> given;
        visited.resize(given.length());
        for (int i = 0; i < given.length(); i++) { indices[given[i]] = i; }
        recursion("");
        return 0;
    }