开发者

Anagram generator for C++ (not using STL)

I am trying to create an anagram solver just using a very basic, procedural appro开发者_如何学Pythonach. I am finding out that I probably should have done this using classes, but now it is too late and my assignment is about due. Any suggestions on how to figure this out would be great!

Basically, this is what the algorithm should do:

  1. Get all words in the dictionary; store them in a container
  2. Get a word from the user; quit if appropriate
  3. Get all permutations of the word that the user entered
  4. Strip the word the user entered from the permutations
  5. Strip all words in the permutation collection that aren't also in the dictionary I collected in part 1

Now for the last step, I must make sure that I don't display duplicate anagrams (i.e. anagrams which contain the same letter, such as "loop"). I cannot seem to get this check to work, which is noted below with under the TODO comment block.

Any suggestions would be awesome!!

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


You may want to rethink your step (3). If the user enters a 12-letter word you have 479,001,600 permutations of it which will probably be impractical to assemble all at once (and if that's not, then a 16-letter word will be...).

Instead, try thinking about how you could store the words and look up potential anagrams in a way that doesn't require you to do that.

Edit: I get that ability to solve largeish words may not be your biggest concern at this point, but it might actually make your fourth and fifth steps easier if you do them by assembling the set of valid words rather than starting with all possibilities and removing all the ones that don't match. 'Removing' an item from an array is a bit awkward since you have to shuffle all the following items up to fill in the gap (this is exactly the kind of thing that STL manages for you).


Better algorithm : don't store your word, but store a tupple containing (your word, sorted letters). Moreover, you sort that big storage by the second key (hint, you could use a sqlite database to do the work for you and use an index (can't be unique!))

E.g. to store

"Florent", "Abraham","Zoe"

you would store in memory

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

When you got your word from your user, you just use same "sorting letter inside word" algorithm.

Then you look for that pattern in your storage, and you find all anagrams very quickly (log(size of dictionary)) as it's sorted. Of course, original words are the second elements of your tuple.

You can do that using classes, standard structures, a database, up to you to choose the easiest implementation (and the one fitting your requirements)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜