C++ 的字谜生成器(不使用STL)
我正在尝试使用非常基本的程序方法创建一个字谜求解器。我发现我可能应该使用类来完成此操作,但现在为时已晚,我的作业即将到期。任何关于如何解决这个问题的建议都会很棒!
基本上,这就是算法应该做的事情:
- 获取字典中的所有单词;将它们存储在容器中
- 从用户那里获取一句话;如果合适则退出
- 获取用户输入的单词的所有排列
- 从排列中删除用户输入的单词
- 删除排列集合中不在我在第 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;
}
I am trying to create an anagram solver just using a very basic, procedural approach. 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:
- Get all words in the dictionary; store them in a container
- Get a word from the user; quit if appropriate
- Get all permutations of the word that the user entered
- Strip the word the user entered from the permutations
- 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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可能需要重新考虑您的步骤 (3)。如果用户输入一个 12 个字母的单词,您将获得 479,001,600 个排列,这可能无法一次组合所有(如果不是,那么将是一个 16 个字母的单词......)。
相反,尝试考虑如何存储单词并以不需要您这样做的方式查找潜在的字谜词。
编辑:我知道解决大单词的能力可能不是您目前最关心的问题,但如果您通过组装有效单词集而不是从所有可能性开始并删除来完成它们,实际上可能会使您的第四步和第五步更容易所有不匹配的。从数组中“删除”一个项目有点尴尬,因为您必须将所有后续项目打乱以填补空白(这正是 STL 为您管理的事情)。
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).
更好的算法:不存储您的单词,而是存储包含(您的单词、排序字母)的元组。此外,您可以通过第二个键对大存储进行排序(提示,您可以使用 sqlite 数据库来为您完成工作并使用索引(不能是唯一的!))
例如,要存储
您将存储在内存中
当您得到您从用户那里得到的单词,您只需使用相同的“在单词内排序字母”算法即可。
然后,您在存储中查找该模式,并且在排序后很快就能找到所有字谜词 (
log(字典大小)
)。当然,原始单词是元组的第二个元素。您可以使用类、标准结构、数据库来做到这一点,由您选择最简单的实现(以及符合您要求的实现)
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
you would store in memory
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)