簡體   English   中英

C++ 的字謎生成器(不使用 STL)

[英]Anagram generator for C++ (not using STL)

我正在嘗試使用一種非常基本的程序方法來創建一個字謎求解器。 我發現我可能應該使用課程來完成這項工作,但現在為時已晚,我的作業即將到期。 任何關於如何解決這個問題的建議都會很棒!

基本上,這是算法應該做的:

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

您可能需要重新考慮您的步驟 (3)。 如果用戶輸入一個 12 個字母的單詞,那么您有 479,001,600 個排列組合,這可能是不切實際的一次組裝(如果不是這樣,那么 16 個字母的單詞將是......)。

相反,請嘗試考慮如何存儲單詞並以不需要您這樣做的方式查找潛在的字謎。

編輯:我知道解決大詞的能力可能不是你目前最關心的問題,但如果你通過組裝一組有效詞而不是從所有可能性開始並刪除它們,它實際上可能會讓你的第四步和第五步更容易所有不匹配的。 從數組中“刪除”一個項目有點尷尬,因為您必須將以下所有項目重新排列以填補空白(這正是 STL 為您管理的事情)。

更好的算法:不要存儲你的單詞,而是存儲一個包含(你的單詞,排序的字母)的元組。 此外,您通過第二個鍵對大存儲進行排序(提示,您可以使用 sqlite 數據庫為您完成工作並使用索引(不能是唯一的!))

例如存儲

"Florent", "Abraham","Zoe"

您將存儲在 memory

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

當您從用戶那里得到您的消息時,您只需使用相同的“在單詞中排序字母”算法。

然后你在你的存儲中尋找那個模式,你很快就會找到所有的字謎( log(size of dictionary) ),因為它是排序的。 當然,原始詞是元組的第二個元素。

您可以使用類、標准結構、數據庫來做到這一點,由您選擇最簡單的實現(以及適合您要求的實現)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM