#include <iostream>
#include <random>
#include <ctime>

using namespace std;


typedef mt19937 MyRNG;
// uint32_t seed_val;

MyRNG rng;
bool rngInitialized = false;

const string ALPHABET = "abcdefghijklmnopqrstuvwxyz ";
const string DESIRED_STRING = "methinks it is like a weasel"; 


void initialize_random() {
	rng.seed(time(0));
}


int randint(int start, int end) {
	if (!rngInitialized) {
		initialize_random();
		rngInitialized = true;
	}

	uniform_int_distribution<uint32_t> myDist(start, end);
	return myDist(rng);
}


string generate_string(string seed) {
	string result;
	for (int i = 0; i < DESIRED_STRING.length(); i++) {
		if (seed[i] == DESIRED_STRING[i]) {
			result = result + seed[i];
		} else {
			result = result + ALPHABET[randint(0, 26)];
		}
	}
	return result;
}


string generate_string() {
	string seed;
	for (int i = 0; i < DESIRED_STRING.length(); i++) {
		seed = seed + '-';
	}
	return generate_string(seed);
}


int appraise_string(string str) {
	if (str == DESIRED_STRING) {
		return 100;
	}

	int correct = 0;
	for (int i = 0; i < str.length(); i++) {
		if (str[i] == DESIRED_STRING[i]) {
			correct++;
		}
	}

	return (correct * 100) / DESIRED_STRING.length();
} 


int main() {
	string res = generate_string();
	int current_attempt = appraise_string(res);
	int best_attempt = current_attempt;
	string best_attempt_str = res;

	int counter = 0;
	while(current_attempt != 100) {
		res = generate_string(best_attempt_str);
		current_attempt = appraise_string(res);

		if (current_attempt > best_attempt) {
			best_attempt = current_attempt;
			best_attempt_str = res;
		}

		if (counter == 1000) {
			cout << "Current best attempt with " << best_attempt << "%: " << best_attempt_str << endl;
			counter = 0;
		}

		counter++;
	}
	
	cout << "Generated result with counter at " << counter << endl;
	return 0;
}