如何在不递归的情况下找到所有可能的字谜?

Posted

技术标签:

【中文标题】如何在不递归的情况下找到所有可能的字谜?【英文标题】:How to find all possible anagrams without recursion? 【发布时间】:2019-10-20 12:44:53 【问题描述】:

我正在尝试构建一个程序来查找单词的所有字谜。这将采用“123”并将其转换为“132”、“213”、“231”、“312”、“321”(以不相关的顺序)。我在How can I get all the anagrams of a string 看到过帖子,但我希望使用普通循环而不是函数递归来执行此操作。到目前为止,我的字谜函数是这样的:

void inline decodeAnagram(string anagram) 
    srand(time(0)); // Get truly random numbers
    while (amount != possibilities) 
        bool failedCheck = false;
        // Create array from letters
        char splitAnagram[1024];
        strcpy_s(splitAnagram, anagram.c_str());

        // Main loop
        for (int i = anagram.length() - 1; i > 0; i--) 
            int index = rand() % i + 1;
            char letter = splitAnagram[index];
            splitAnagram[index] = splitAnagram[i];
            splitAnagram[i] = letter;
        

        // Loop to get valid array parts back to string
        string result = "";
        for (int i = 0; i <= anagram.length(); i++) 
            result += splitAnagram[i];
        

        // Check if value is already in vector
        for (int i = 0; i < guesses.size(); i++) 
            if (result == guesses[i]) 
                failedCheck = true;
                break;
            
        
        if (failedCheck == false)  // Value is not already in vector
            guesses.push_back(result);
            amount++;
            cout << result << endl;
        
    

但是,这只给了我第一个字母的字谜。例如,如果我的字谜是“1234”,则程序只返回“1234”、“1243”、“1324”、“1342”、“1423”和“1432”。如果您没有看到其中的模式,请注意第一个字符始终相同

我不确定为什么我的程序没有进一步发展。完成后,它只是挂起全速运行(可能会生成已经猜到的单词并一次又一次地运行)。

运行它的完整代码在这里:

// File created on June 4, 2019

#include <iostream>
#include <Windows.h>
#include <iomanip>
#include <vector>
#include <string>

using namespace std;

bool stop = false;
int amount = 0;
int possibilities = 1;
string anagram;
vector<string> guesses;


void inline decodeAnagram() 
    srand(time(0));
    while (amount != possibilities) 
        bool failedCheck = false;
        // Create array from letters
        char splitAnagram[1024];
        strcpy_s(splitAnagram, anagram.c_str());

        // Main loop
        for (int i = anagram.length() - 1; i > 0; i--) 
            int index = rand() % i + 1;
            char letter = splitAnagram[index];
            splitAnagram[index] = splitAnagram[i];
            splitAnagram[i] = letter;
        

        // Loop to get valid array parts back to string
        string result = "";
        for (int i = 0; i <= anagram.length(); i++) 
            result += splitAnagram[i];
        

        // Check if value is already in vector
        for (int i = 0; i < guesses.size(); i++) 
            if (result == guesses[i]) 
                failedCheck = true;
                break;
            
        
        if (failedCheck == false)  // Value is not already in vector
            guesses.push_back(result);
            amount++;
            cout << result << endl;
        
    


int main() 
    // Welcome the user and get the anagram to decode
    cout << "Welcome to the Anagram Decoder!" << endl;
    cout << "What do you want your anagram to be? > ";
    cin >> anagram;
    cout << endl << "Attempting to decode " << anagram << endl;

    for (int i = anagram.length(); i > 0; i--) 
        possibilities = possibilities * i;
    

    cout << possibilities << " possibilities" << endl;

    clock_t start = clock();
    decodeAnagram();

    cout << "Decoded the anagram " << anagram << " in " << setprecision(2) << fixed << (float)(clock() - start) / CLOCKS_PER_SEC << " seconds." << endl << endl << "That's about " << setprecision(0) << amount / ((float)(clock() - start) / CLOCKS_PER_SEC) << " anagrams per second!" << endl;
    return 0;

【问题讨论】:

优先使用std::vector&lt;std::string&gt;而不是char数组。 你考虑过std::next_permutation吗? srand(time(0)); // Get truly random numbers 哈哈 // Create array from letters -- 为什么?在整个尝试过程中使用 std::string 有什么问题? randsrand(time(0)) 远非真正随机。如果您不打算使用更好的 C++ &lt;random&gt; 工具,至少在程序开始时只调用一次 srand 【参考方案1】:

您可以使用std::next_permutation 轻松做到这一点:

#include <algorithm>
#include <iostream>
#include <string>

int main()

  std::string test = "1234";
  std::sort(test.begin(), test.end());  // sort sequence first
  do
  
     std::cout << test << "\n";
   while (std::next_permutation(test.begin(), test.end()));
   

输出:

1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321

【讨论】:

如果 OP 有兴趣了解它的工作原理,也可以查看 next_permutation 的源代码 是的,在 cppreference 链接上是一个可能的实现。没有使用递归。 几年前,Mark Nelson 写了(我认为是)相当不错的article on next_permutation

以上是关于如何在不递归的情况下找到所有可能的字谜?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不停止递归的情况下返回递归函数中的值?

如何在不使用重命名命令的情况下递归搜索目录并从文件名中删除开/关括号? [复制]

算法回溯:如何在不存储状态的情况下进行递归

Firestore - 如何在不真正获取所有文档的情况下找到可以使用查询获取的文档数量? [复制]

我想反转堆栈,但我不知道如何使用递归来反转这个......如何在不使用递归的情况下反转堆栈

如何在不使用递归或`/`运算符的情况下进行除法?