Tiimie1
Tiimie1

Reputation: 23

C++ Anagram Solver speed optimization

I have decided to make an anagram solver for my dad. I am quite new to programming, but i figured I can still make it. My finished product works, but it is really slow, for instance it took about 15+ mins to find all combinations of 8 characters. I am looking for ways to optimize it / make it faster.

Working with MinGW c++ compier, on Clion 2019.3.4, cpu: i7 9700k, and RAM: 16GB/3200mhz.

#include <iostream>
#include <string>
#include <vector>
#include <fstream>

using namespace std;

//Menu for interacting with user, not really important
void menu() {
    cout << "=========================" << endl;
    cout << "======== !WOW! ==========" << endl;
    cout << "=========================" << endl;
    cout << "1 ... INSERT" << endl;
    cout << "2 ... PRINT" << endl;
    cout << "3 ... LIMIT WORD LENTGH" << endl;
    cout << "4 ... NEW GAME" << endl;
    cout << "0 ... EXIT" << endl;
    cout << "=========================" << endl;
    cout << "Select: ";
}

//Function to find all possible combinations from letters of a given string 
void get(vector<string> &vec, string str, string res) {

    vec.push_back(res);

    for (int i = 0; i < str.length(); i++)
        get(vec, string(str).erase(i, 1), res + str[i]);
}

//Only for testing purposes
void printVec(vector<string> vec) {
    for (int i = 0; i < vec.size(); i++) {
        cout << vec[i] << " ";
    }
}

//Function to check if a given word exists in given .txt file
bool checkWord(vector<string> &vec2, string filename, string search) {

    string line;
    ifstream myFile;
    myFile.open(filename);

    if (myFile.is_open()) {
        while (!myFile.eof()) {
            getline(myFile, line);
            if (line == search) {
                vec2.push_back(line);
                return true;
            }
        }
        myFile.close();
    } else
        cout << "Unable to open this file." << endl;

    return false;
}


int main() {

    int selection;
    bool running = true;
    string stringOfChars;
    vector<string> vec;
    vector<string> vec2;

    do {

        menu();
        cin >> selection;
        switch (selection) {

            case 1:
                cout << "Insert letters one after another: ";
                cin >> stringOfChars;
                get(vec, stringOfChars, ""); //fill first vector(vec) with all possible combinations.
                break;

            case 2:
                for (int i = 0; i < vec.size(); i++) {
                    if (checkWord(vec2, "C:/file.txt", vec[i])) { //For each word in vector(vec) check if exists in file.txt, if it does, send it in vector(vec2) and return true
//Reason for vec2's existence is that later I want to implement functions to manipulate with possible solutions (like remove words i have already guessed, or as shown in case 3, to limit the word length)
                        cout << vec[i] << endl; //If return value == true cout the word
                    }
                }
                break;

            case 3:
                int numOfLetters;
                cout << "Word has a known number of letters: ";
                cin >> numOfLetters;
                for (int i = 0; i < vec2.size(); i++) { /*vec2 is now filled with all the answers, we can limit the output if we know the length of the word */
                    if (vec2[i].length() == numOfLetters) {
                        cout << vec2[i] << endl;
                    }
                }
                break;

            case 4:
                vec.clear();
                vec2.clear();
                break;

            case 0:
                running = false;
                break;

            default:
                cout << "Wrong selection!" << endl;
                break;
        }
        cout << endl;
    } while (running);

    return 0;
}


file.txt is filled with all words in my language, It's alphabetically ordered and it's 50mb in size.

aachecnska
aachenskega
aachenskem
aachenski
.
.
.
bab
baba
babah
.
.
.

Any recommendations or off topic tips would be helpful. One of my ideas is to maybe separate file.txt in smaller files, like for example putting lines that have same starting letter in their own file, so A.txt would only contain words that start with A etc... And than change the code accordingly.

Upvotes: 2

Views: 208

Answers (1)

FangQ
FangQ

Reputation: 1544

this is where you need to use a profiler. on Linux, my favorite is kcachgrind

http://kcachegrind.sourceforge.net/html/Home.html

it gives you line-by-line timing information and tells you which part of the code you should optimize the most.

of course, there are many profilers available, including commercial ones.

Upvotes: 1

Related Questions