Генератор анаграмм для C ++ (без использования STL) - PullRequest
0 голосов
/ 04 июля 2011

Я пытаюсь создать решатель анаграмм, используя очень простой процедурный подход.Я выясняю, что, вероятно, я должен был сделать это, используя классы, но сейчас уже слишком поздно, и мое задание закончено.Любые предложения о том, как это выяснить, были бы хорошими!

По сути, именно это и должен делать алгоритм:

  1. Получить все слова в словаре;хранить их в контейнере
  2. Получить слово от пользователя;выйти, если необходимо
  3. Получить все перестановки слова, введенного пользователем
  4. Убрать слово, введенное пользователем из перестановок
  5. Убрать все слова в коллекции перестановок, которые не 't также в словаре, который я собрал в части 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;
}

Ответы [ 2 ]

2 голосов
/ 04 июля 2011

Лучший алгоритм: не храните свое слово, но храните набор, содержащий (ваше слово, отсортированные буквы).Более того, вы сортируете это большое хранилище по второму ключу (подсказка, вы можете использовать базу данных sqlite, чтобы выполнить работу за вас, и использовать индекс (не может быть уникальным!))

Например, для хранения

"Florent", "Abraham","Zoe"

вы бы сохранили в памяти

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

Когда вы получили слово от своего пользователя, вы просто используете тот же алгоритм "сортировки букв внутри слова".

Тогда выпоищите этот шаблон в своем хранилище, и вы найдете все анаграммы очень быстро (log(size of dictionary)) по мере их сортировки.Конечно, оригинальные слова - это вторые элементы вашего кортежа.

Вы можете сделать это, используя классы, стандартные структуры, базу данных, чтобы вы могли выбрать простейшую реализацию (и ту, которая соответствует вашим требованиям)

2 голосов
/ 04 июля 2011

Вы можете переосмыслить свой шаг (3).Если пользователь вводит 12-буквенное слово, у вас есть 479 001 600 перестановок, которые, вероятно, нецелесообразно собирать все сразу (а если это не так, то 16-буквенное слово будет ...).

Вместо этого попробуйте подумать о том, как вы могли бы хранить слова и искать потенциальные анаграммы таким образом, чтобы вам этого не требовалось.

Редактировать: я получаю, что способность решать большие слова может быть не самой большойОбеспокоенность в этом вопросе, но на самом деле это может упростить ваши четвертый и пятый шаги, если вы выполните их, собрав набор допустимых слов, а не начав со всех возможностей и удалив все те, которые не совпадают.«Удаление» элемента из массива немного неловко, так как вам нужно перетасовать все последующие элементы, чтобы заполнить пробел (это именно та вещь, которой управляет STL для вас).

...