【问题标题】:Anagram generator for C++ (not using STL)C++ 的字谜生成器(不使用 STL)
【发布时间】:2011-09-27 21:03:23
【问题描述】:

我正在尝试使用一种非常基本的程序方法来创建一个字谜求解器。我发现我可能应该使用课程来完成这项工作,但现在为时已晚,我的作业即将到期。任何关于如何解决这个问题的建议都会很棒!

基本上,这就是算法应该做的:

  1. 获取字典中的所有单词;将它们存放在容器中
  2. 从用户那里得到一个字;适当时退出
  3. 获取用户输入的单词的所有排列
  4. 从排列中去除用户输入的单词
  5. 去除排列集合中不在我在第 1 部分收集的字典中的所有单词

现在对于最后一步,我必须确保不显示重复的字谜(即包含相同字母的字谜,例如“循环”)。我似乎无法让这个检查工作,这在下面的 TODO 注释块下进行了说明。

任何建议都会很棒!

#include <iostream>
#include <fstream>
#include <string>

//
// Change size below to accomodate more anagrams and dictionary words
//
#define MAX_ANGM_SIZE  4096
#define MAX_WORD_SIZE  1048576

using namespace std;


//
// Determines whether anagram is valid or not; will not display word
// which user entered or words not contained in dictionary
//
bool isValidAnagram(string word, string userWord,
                string dictionary[], unsigned int listIdx)
{
    for(unsigned int idx = 0; idx < listIdx; ++idx)
    {
        if(word == userWord)
            return false;
        else if (word == dictionary[idx])
            return true;
    }

    return false;
}


//
// Determines whether user's word is contained in the dictionary
// or not
//
bool isValidWord(string word, string dictionary[], 
             unsigned int listIdx)
{
    for(unsigned int idx = 0; idx < listIdx; ++idx)
    {
        if(word == dictionary[idx])
            return true;
    }

    return false;
}


//
// TODO:This function should test for duplicate anagrams and return
// true if duplicates are found.
//
bool isRepeated(string anagrams[], unsigned int anaIdx)
{
    for(unsigned int idx = anaIdx; idx != 0; --idx)
    {
        if(anagrams[idx] == anagrams[anaIdx])
            return true;
        else 
            return false;
    }

    return false;
}


//
// Only display elements in array which aren't blank and don't 
// display duplicate anagrams; notify user if no anagrams
// were found.
//
void displayAnagrams(string anagrams[], unsigned int next)
{
    int flag = 0;

    for (unsigned int idx = 0; idx < next; ++idx)
    {

        if((anagrams[idx] != "") || (!(isRepeated(anagrams, idx))))
        {
            if(idx == 1)
                cout << "  Anagrams: ";
            if(idx > 0)
                flag = 1;

            cout << anagrams[idx] << " ";
        }
        else 
            continue;
    }

    if(flag == 0)
        cout << "  no anagrams found" << endl;
}


static void swap(char &c1, char &c2)
{
    char temp = c1;

    c1 = c2;
    c2 = temp;
}


//
// Pass in word to be altered, the userWord for comparison, the array to store
// anagrams, the dictionary for comparison, the count for the number of anagrams
// and the count for number of dictionary words
//
static void permute(string word, string userWord, int k, string anagrams[],
                string dictionary[], unsigned int &next, unsigned    int listIdx)
{   
    if(k == word.length()-1)
    {
        if(isValidAnagram(word, userWord, dictionary, listIdx))
            anagrams[next] = word;

        ++next;
    }
    else
    {
        for(int idx = k; idx < word.length(); ++idx)
        {
            swap(word[k], word[idx]);
            permute(word, userWord, k+1, anagrams, dictionary, next, listIdx);
        }
    }
}


//
// Create container to store anagrams, validate user's word in dictionary, get all
// of the anagrams, then display all valid anagrams
//
void getAnagrams(string word, string dictionary[], unsigned int listIdx)
{
    string anagrams[MAX_ANGM_SIZE];
    unsigned int next = 0;

    if(isValidWord(word, dictionary, listIdx))
    {
        permute(word, word, 0, anagrams, dictionary, next, listIdx);
    }
    else
    {
        cerr << "  \"" << word << "\"" << " is not a valid word" << endl;
        return;
    }

    displayAnagrams(anagrams, next);
}


//
// Read in dictionary file, store contents of file in a list, prompt
// the user to type in words to generate anagrams
//
int main()
{
    string file;
    string word;
    string quit = "quit";
    string dictionary[MAX_WORD_SIZE];

    unsigned int idx = 0;

    cout << "Enter a dictionary file: ";
    cin  >> file;
    cout << "Reading file \"" << file << "\"" << endl;
    cout << endl;

    ifstream inFile(file.c_str());

        if(!(inFile.is_open())) 
    {
        cerr << "Can't open file \"" << file << "\""
         << endl;

        exit(EXIT_FAILURE);
    }

    while(!inFile.eof())
    {
        inFile >> dictionary[idx];
        ++idx;
    }

    inFile.close();

    while(true)
    {
        cout << "Enter a word: ";
        cin  >> word;

        if(word == quit) break;

        getAnagrams(word, dictionary, idx);

        cout << endl;
    }

    return 0;
}

【问题讨论】:

  • 为什么要避免使用 STL? (毕竟您使用的是string,它符合STL 容器的大部分要求……)
  • 这其实是给STL上的一个类的,但这是第一次作业,我还没用过STL。此作业的目标是使用标准技术,然后在我们知道如何使用 STL 后在学期末做完全相同的作业。
  • 啊,我明白了。好吧,只是一个 FYI——std::string 公开了一个主要是 STL 序列容器接口。 (但是,如果您想学究气,字符串库会早于 STL 包含在标准中一段时间​​)
  • 如果是作业,请加tag homework
  • @Dylan:很遗憾听到这是你们学校的学习方法(顺便说一句,我的学习方法是一样的)。你可能想向你的导师建议,反过来可能会更好:学习如何使用高级构造来解决问题,并在你这样做的同时学习语言和解决问题的基础知识。然后学习更难的低级细节,重新实现您已经手动完成的内容,目标不是解决问题(此时会知道算法),而是解决手动实现的细节。

标签: c++ string fstream anagram


【解决方案1】:

您可能需要重新考虑您的步骤 (3)。如果用户输入一个 12 个字母的单词,那么您有 479,001,600 个排列组合,这可能是不切实际的一次组装(如果不是这样,那么 16 个字母的单词将是......)。

相反,请尝试考虑如何以不需要您这样做的方式存储单词并查找潜在的字谜。

编辑:我知道解决大词的能力可能不是你目前最关心的问题,但如果你通过组装一组有效词而不是从所有开始来完成第四步和第五步,它实际上可能会让你的第四步和第五步更容易可能性并删除所有不匹配的可能性。从数组中“删除”一个项目有点尴尬,因为您必须将以下所有项目重新排列以填补空白(这正是 STL 为您管理的那种事情)。

【讨论】:

  • 是的,我也想过。 12 阶乘是一个丑陋的数字。但是,嘿,如果它有效(即使它不切实际),我会采取我能得到的。谢谢。
【解决方案2】:

更好的算法:不要存储你的单词,而是存储一个包含(你的单词,排序的字母)的元组。此外,您通过第二个键对大存储进行排序(提示,您可以使用 sqlite 数据库为您完成工作并使用索引(不能是唯一的!))

例如存储

"Florent", "Abraham","Zoe"

你会存储在内存中

("aaabhmr", "abraham"),("eflnort","florent"),("eoz","zoe")

当你从你的用户那里得到你的话时,你只需使用相同的“在单词中排序字母”算法。

然后您在存储中查找该模式,并在排序后很快找到所有字谜 (log(size of dictionary))。当然,原始词是元组的第二个元素。

您可以使用类、标准结构、数据库来做到这一点,由您选择最简单的实现(并且满足您的要求)

【讨论】:

    猜你喜欢
    • 2010-12-23
    • 2010-09-08
    • 2016-04-22
    • 1970-01-01
    • 1970-01-01
    • 2015-09-23
    • 1970-01-01
    • 2014-05-09
    • 2019-07-10
    相关资源
    最近更新 更多