在一个C++函数中交换向量中的两个元素。

huangapple go评论82阅读模式
英文:

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

问题

我必须编写一个程序,该程序以单词作为输入。输入中的字母应随机排序,直到恢复初始单词。

要检查是否恢复了初始顺序,需要在标志链前面打印字母的索引。

例如,期望的输出如下:

[1] 0123 Test

[2] 3201 tsTe

[3] 2103 seTt

以此类推。

为此,我定义了一个名为signchain的字符串作为初始输入,并定义了一个包含0到n(输入单词的长度)的数字的向量indexes

字母的随机重新排列是有效的,但我无法交换向量中的索引。

在我附上的代码中,函数应该执行以下操作:

  • mix_cycle:从定义signchainindexes到在恢复初始单词时停止循环的整个过程。
  • form_new_word_by_indexes:根据给定单词和其中字母的索引创建一个新单词。应随机交换多少个字母以及交换哪些字母应该是随机的。在这个函数中,应根据交换的字母交换索引。
  • getRandomNumber:在特定区间内生成一个随机数。

我的问题是:如何根据字母交换索引?我已经尝试过std::swap,但无法使其正常工作。

// 选择两个给定值之间的随机数的函数
static uint16_t getRandomNumber(uint16_t min, uint16_t max)
{
    uint16_t rand_num = rand() % (max - min) + min;
    return rand_num;
}

// 根据给定单词和字母的索引创建新单词的函数
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();
    std::string new_word = initial_word;
    char element_memory;
    uint16_t index_1, index_2;

    for (int i = 0; i <= getRandomNumber(min, max); i++)
    {
        while (true) {
            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;

        // 交换索引
        std::swap(indexes[index_1], indexes[index_2]);
    }

    return new_word;
}

// 程序的主循环:随机重新排列给定单词中的字母,直到恢复为止
void mix_cycle(const std::string& initial_word)
{
    int am_letters = initial_word.length();
    std::string signchain = initial_word;
    std::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;
        std::cout << "[" << counter << "] ";
        signchain = form_new_word_by_indexes(signchain, index_list);
        for (int i = 0; i < index_list.size(); i++)
        {
            std::cout << index_list[i];
        }
        std::cout << " ";
        for (int i = 0; i < am_letters; i++)
        {
            std::cout << signchain[i];
        }
        std::cout << "\n";
    }
}
英文:

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&amp; initial_word, const std::vector&lt;uint16_t&gt;&amp; 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 &lt;= getRandomNumber(min, max); i++)		//zuf&#228;llige Anzahl an Tauschvorg&#228;ngen wird durchgef&#252;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&amp; 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&lt;uint16_t&gt; index_list;
for (int i = 0; i &lt; am_letters; i++)
{
index_list.push_back(i);
}
int counter = 0;
while (true)
{
counter += 1;
cout &lt;&lt; &quot;[&quot; &lt;&lt; counter &lt;&lt; &quot;] &quot;;
signchain = form_new_word_by_indexes(signchain,index_list);
for (int i = 0; i &lt; index_list.size(); i++)
{
cout &lt;&lt; index_list[i];
}
cout &lt;&lt; &quot; &quot;;
for (int i = 0; i &lt; am_letters; i++)
{
cout &lt;&lt; signchain[i];
}
cout &lt;&lt; &quot;\n&quot;;
}
}

答案1

得分: 2

首先,对于算法部分,如果您想要交换索引,就像您交换字符串一样,我会创建一个字符串,类似于012...n,命名字符串中字母当前位置的索引,并在这个字符串中交换位置,就像您交换字母一样。

举例说明,考虑输入:

Test

我会创建这个索引字符串:

0123

如果您交换两个字母,比如第一个 T 和 e,第一个字符串将变成:

eTst

现在在索引字符串中交换相同的位置:

1023

然后您就可以得到您的索引字符串。

现在,为了实现这个交换的目标,您可以手动完成,或者使用您已经正确使用的swap()函数:

手动方法:

char temp = str[i]; // i 是要交换的位置的索引
str[i] = str[j];   // j 是另一个索引
str[j] = temp;

然而,您的问题是必须确保您的向量不是const,否则swap()函数将无法工作,因为常量向量无法被编辑。

现在,您的整个问题似乎可以用更简单和更短的代码来解决。根据描述,您只需要以随机顺序排列的字母,而不仅仅是交换字母。您可以使用递归和一个简单的映射来实现这一点。换句话说,创建所有排列的序列的整个代码如下:

#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;
}

这段代码可以生成所有排列的序列。

英文:

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 &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;unordered_map&gt;
std::string given;
std::vector &lt;bool&gt; visited;
std::unordered_map &lt;char, int&gt; indices;
void recursion(std::string word) {
if (word.length() == given.size()) {
for (char x : word) { std::cout &lt;&lt; indices[x]; }
std::cout &lt;&lt; &#39; &#39; &lt;&lt; word &lt;&lt; &#39;\n&#39;;
return;
}
for (int i = 0; i &lt; given.size(); i++) {
if (!visited[i]) {
visited[i] = true;
recursion(word + given[i]);
visited[i] = false;
}
}
}
int main() {
std::cin &gt;&gt; given;
visited.resize(given.length());
for (int i = 0; i &lt; given.length(); i++) { indices[given[i]] = i; }
recursion(&quot;&quot;);
return 0;
}

huangapple
  • 本文由 发表于 2023年6月11日 19:58:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76450369.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定