寻找更快的方法来帮助减少/创建大量的字符串

时间:2019-05-01 11:24:46

标签: c++ data-structures runtime

我试图编写一种算法来在“ Masterminds”游戏中正确猜测,
它的平均猜测数目为6,但是计算最佳猜测花费大量时间。

我使用Knuth的想法,算法的工作原理如下:

  
      
  1. 创建1296个可能的代码(1111、1112 ... 6665、6666)的集合S。
  2.   
  3. 从初始猜测1122开始(Knuth给出的示例显示,其他第一猜测(例如1123、1234)在五次尝试中均未获胜   每个代码)。
  4.   
  5. 进行猜测以获得彩色和白色钉子的响应。
  6.   
  7. 如果响应是四个彩色钉子,则赢得比赛,算法终止。
  8.   
  9. 否则,如果当前猜测是代码,则从S中删除任何不会给出相同响应的代码。
  10.   

在我的代码中,步骤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);
}

1 个答案:

答案 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());