我试图编写一种算法来在“ Masterminds”游戏中正确猜测,
它的平均猜测数目为6,但是计算最佳猜测花费大量时间。
我使用Knuth的想法,算法的工作原理如下:
- 创建1296个可能的代码(1111、1112 ... 6665、6666)的集合S。
- 从初始猜测1122开始(Knuth给出的示例显示,其他第一猜测(例如1123、1234)在五次尝试中均未获胜 每个代码)。
- 进行猜测以获得彩色和白色钉子的响应。
- 如果响应是四个彩色钉子,则赢得比赛,算法终止。
- 否则,如果当前猜测是代码,则从S中删除任何不会给出相同响应的代码。
在我的代码中,步骤2是获取随机数。
我为此使用了vector<string>
。
AllPoss
是充满字符串的向量,我猜是最后使用的猜测。 answer
是公牛和母牛的数目,看起来像“ x,y”(其中x和y是数字)
void bullpgia::SmartGuesser::remove(string guess, string answer)
{
for (auto i= AllPoss.begin();i != AllPoss.end();i++){
string token = *i;
if (calculateBullAndPgia(token, guess) != answer)
AllPoss.erase(i--);
}
}
这是需要很多时间来计算的部分,是否有任何改进的方法?
创建我使用的列表:
void bullpgia::SmartGuesser::All() {
/**
* creates a pool of all the possibilities strings
* we then delete the ones we dont need
* @param length is the length of the word we need to guess
*/
for(int i=0;i<pow(10,length);i++){
stringstream ss;
ss << setw(length) << setfill('0') << i;
string s = ss.str();
AllPoss.push_back(s);
}
}
computeBullAndPgia(string,string)函数是:
string calculateBullAndPgia(const string &choice, const string &guess) {
string temp = choice;
string temp2 = guess;
unsigned int bull = 0;
unsigned int pgia = 0;
for (int i = 0; i < temp.length(); i++) {
if (temp[i] == temp2[i]) {
bull++;
temp[i] = 'a';
temp2[i] = 'z';
}
}
for (int i = 0; i < temp.length(); i++) {
for (int j = 0; j < temp2.length(); j++) {
if (i != j && temp[i] == temp2[j]) {
pgia++;
temp[i] = 'a';
temp2[j] = 'z';
}
}
}
return to_string(bull) + "," + to_string(pgia);
}
答案 0 :(得分:3)
在向量中间擦除单个元素是O(n)。我的猜测是,每次调用SmartGuesser::remove
时,您要进行O(n)次操作。然后,您可以对其进行遍历,从而可能拥有O(n ^ 3)算法。相反,您可以使用std::remove_if
(即O(n))将所有要擦除的元素移到向量的末尾,从而可以廉价地擦除它们。:
AllPoss.erase(std::remove_if(AllPos.begin(), AllPos.end(), [&](const std::string& token, const std::string& guess) { return calculateBullAndPgia(token, guess) != answer; }), AllPos.end());