【发布时间】:2018-12-01 18:12:27
【问题描述】:
有没有办法保证std::shuffle 产生的输出与输入不同?
下面是一个玩具示例,我在其中玩弄一些旧代码,这些代码可以将单词中的字母打乱,除了第一个和最后一个。我注意到对于短序列std::shuffle 会“随机”将字母打乱到它们的原始位置并产生不希望的输出。所以为了“解决”这个问题,我只是再次重新运行std::shuffle。
简单来说,有没有办法避免 while 循环,或者它只是 std::shuffle 的一个怪癖?
std::string Scramble(const std::string& plaintext) {
static std::random_device rd;
static std::mt19937 g(rd());
std::stringstream ss;
ss << plaintext;
std::vector<std::string> words{};
std::string cur_word;
while(std::getline(ss, cur_word, ' ')) {
if(cur_word.empty()) continue;
words.push_back(cur_word);
}
std::for_each(std::begin(words), std::end(words), [](std::string& word) {
if(word.size() <= 3) {
return;
}
auto old_word = word;
while(old_word == word) {
std::shuffle(std::begin(word) + 1, std::end(word) - 1, g);
}
});
ss.clear();
ss.seekg(0);
ss.seekp(0);
ss.str("");
for(const auto& word : words) {
ss << word << ' ';
}
return ss.str();
}
【问题讨论】:
-
听起来您要求的随机洗牌不是完全随机的?
-
原始排列如何比其他排列更随机?我看不出这怎么能算作“怪癖”。
-
这听起来像是一个与从一个范围内生成唯一“随机”数字的问题相关的问题。
-
经常出现?每 24 次?
-
@Casey 不,当然不经常;它应该在 1/24 的时间内返回它。无论如何,while 循环是执行此标准的最简单方法。任何保证没有身份洗牌的 std::shuffle 替换可能只涉及一个 while 循环本身。