Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <string>
- #include <unordered_map>
- #include <cmath>
- #include <algorithm>
- #include <fstream>
- #include <codecvt>
- enum class LetterInfo {
- GREY,
- YELLOW,
- GREEN
- };
- LetterInfo get_letter_info(wchar_t letter, size_t pos, const std::wstring& ans) {
- auto it = std::find(ans.begin(), ans.end(), letter);
- if (it != ans.end()) {
- return ans[pos] == letter ? LetterInfo::GREEN : LetterInfo::YELLOW;
- } else {
- return LetterInfo::GREY;
- }
- }
- std::vector<std::pair<wchar_t, LetterInfo>> try_guess(const std::wstring& guess, const std::wstring& ans) {
- std::vector<std::pair<wchar_t, LetterInfo>> result;
- for (size_t i = 0; i < guess.size(); ++i) {
- result.emplace_back(guess[i], get_letter_info(guess[i], i, ans));
- }
- return result;
- }
- bool compatible(const std::wstring& noun, const std::vector<std::pair<wchar_t, LetterInfo>>& guess_info) {
- for (size_t i = 0; i < guess_info.size(); ++i) {
- wchar_t letter = guess_info[i].first;
- LetterInfo info = guess_info[i].second;
- bool in_noun = noun.find(letter) != std::wstring::npos;
- if ((info == LetterInfo::GREY) ^ (!in_noun)) {
- return false;
- }
- if (info != LetterInfo::GREY) {
- bool is_green = noun[i] == letter;
- if ((info == LetterInfo::GREEN) ^ is_green) {
- return false;
- }
- }
- }
- return true;
- }
- double score_fixed_guess(const std::vector<std::wstring>& nouns, const std::wstring& opener, const std::wstring& ans) {
- auto guess_info = try_guess(opener, ans);
- size_t total = nouns.size();
- size_t total_compatible = 0;
- for (const auto& noun : nouns) {
- if (compatible(noun, guess_info)) {
- ++total_compatible;
- }
- }
- return std::log2(static_cast<double>(total) / total_compatible);
- }
- double score(const std::vector<std::wstring>& nouns, const std::wstring& opener) {
- double total_score = 0.0;
- for (const auto& ans : nouns) {
- total_score += score_fixed_guess(nouns, opener, ans);
- }
- return total_score / nouns.size();
- }
- std::unordered_map<std::wstring, double> get_scores(const std::vector<std::wstring>& nouns) {
- std::unordered_map<std::wstring, double> scores;
- for (const auto& opener : nouns) {
- scores[opener] = score(nouns, opener);
- if (scores.size() % 100 == 0) {
- std::wcerr << "DBG: progress " << scores.size() << "/" << nouns.size() << "\n";
- }
- }
- return scores;
- }
- std::vector<std::wstring> read_nouns(std::string path) {
- std::ifstream infile(path);
- if (!infile) {
- std::cerr << "Error: Could not open file '" << path << "'\n";
- return {};
- }
- std::vector<std::wstring> nouns;
- std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
- std::string line;
- while (std::getline(infile, line)) {
- if (!line.empty()) {
- nouns.push_back(converter.from_bytes(line));
- }
- }
- infile.close();
- return nouns;
- }
- void write_scores(std::unordered_map<std::wstring, double> scores, std::string path) {
- std::vector<std::pair<std::wstring, double>> scores_vec;
- for (auto entry : scores) {
- scores_vec.push_back(entry);
- }
- sort(scores_vec.begin(), scores_vec.end(), [](auto& a, auto& b) {return a.second > b.second; });
- std::ofstream outfile(path);
- if (!outfile) {
- std::cerr << "Error: Could not open file '" << path << "'\n";
- return;
- }
- std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
- for (const auto& entry : scores_vec) {
- outfile << entry.second << " " << converter.to_bytes(entry.first) << "\n";
- }
- outfile.close();
- }
- int main(int argc, char* argv[]) {
- if (argc != 3) {
- std::cerr << "Usage: opener_scores <words> <output>\n";
- return 0;
- }
- auto nouns = read_nouns(argv[1]);
- auto scores = get_scores(nouns);
- write_scores(scores, argv[2]);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement