Repository navigation
Expand file tree
/
Copy pathmain.cpp
More file actions
180 lines (161 loc) · 7.02 KB
/
Copy pathmain.cpp
File metadata and controls
180 lines (161 loc) · 7.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <utility>
#include <string>
#include <cmath>
#include <map>
#include <algorithm>
#include <fstream>
#include <cmath>
#include <thread>
#include <mutex>
#include "wordle.h"
int main() {
// Read the initial list of words from a file.
std::vector<std::string> words = readWordsFromFile("words.txt");
std::map<std::string, double> freqMap = readFrequencies("frequencies.txt");
// Copy all words from the file into the possibilities vector.
std::vector<std::string> possibilities(words);
std::vector<double> freqs;
// Define the possible colors used in the Wordle game.
std::vector<std::string> colors = {"gray", "yellow", "green"};
// Generate all possible color patterns of length 5.
std::vector<std::vector<std::string>> patterns = cartesian_product(colors, 5);
// A list of precalculated starting words and their corresponding scores.
std::vector<std::pair<std::string, double>> initial = {
{"tares", 6.27},
{"rates", 6.17},
{"tears", 6.15},
{"tales", 6.13},
{"nares", 6.07},
{"tries", 6.06},
{"tires", 6.06},
{"reals", 6.06},
{"saner", 6.05},
{"teals", 6.05}
};
// Display initial top 10 word recommendations.
std::cout << "Top 10 recommendations for your guess are:\n";
for (const auto& pair : initial) {
std::cout << pair.first << " score: " << pair.second << "\n";
}
std::cout << "\n";
// Determine the number of hardware threads available.
const int num_threads = std::thread::hardware_concurrency();
int guess_num = 0; // Counter for the number of guesses.
std::vector<std::string> pat(5); // Vector to store pattern of 5 colors for the guess.
std::vector<std::string> correct = {"green", "green", "green", "green", "green"}; // Target pattern for winning.
bool valid_input;
std::string guess;
// Continue guessing while the pattern is not completely green.
while (pat != correct) {
std::vector<std::pair<double, std::string>> scored_words;
// Validate the user's word guess.
valid_input = false;
while (!valid_input) {
std::cout << "Enter your guess: ";
std::cin >> guess;
// Convert the guess to lowercase for case insensitivity.
std::transform(guess.begin(), guess.end(), guess.begin(), [](unsigned char c){ return std::tolower(c); });
// Ensure the guess is among the possibilities.
if (std::find(words.begin(), words.end(), guess) != words.end()) {
valid_input = true;
} else {
std::cout << "Invalid guess. Please try again." << std::endl;
}
}
// Check if only one possibility remains.
if (possibilities.size() == 1) {
guess_num++;
break;
}
// Get user input for the color pattern of the guessed word.
std::cout << "Enter the pattern of 5 colors (gray: 1, yellow: 2, green: 3) for each letter in your guess: \n";
for (int i = 0; i < 5; ++i) {
valid_input = false;
while (!valid_input) {
std::cout << "Color for position " << i + 1 << ": ";
std::cin >> pat[i];
std::transform(pat[i].begin(), pat[i].end(), pat[i].begin(), [](unsigned char c){ return std::tolower(c); });
if(pat[i] == "1"){
pat[i] = "gray";
}
if(pat[i] == "2"){
pat[i] = "yellow";
}
if(pat[i] == "3"){
pat[i] = "green";
}
// Validate the color input.
if (std::find(colors.begin(), colors.end(), pat[i]) != colors.end()) {
valid_input = true;
} else {
std::cout << "Invalid color. Valid options are 'gray', 'yellow', 'green'. Please enter a valid color." << std::endl;
}
}
}
std::cout << "\n";
//if guess is correct, stop
if(pat == correct){
++guess_num;
break;
}
// Generate new possibilities based on the guess and pattern.
possibilities = generate_words(pat, guess, possibilities);
// Handle case where no words match the input pattern.
if (possibilities.size() == 0) {
std::cout << "We couldn't figure out the word.";
return 0;
}
// Start multiple threads to compute scores for the remaining possibilities.
std::vector<std::thread> threads;
int chunk_size = words.size() / num_threads;
for (int i = 0; i < num_threads; ++i) {
int start = i * chunk_size;
int end = (i + 1) * chunk_size;
if (i == num_threads - 1) end = words.size(); // Ensure the last thread covers all elements
threads.emplace_back(compute_scores, std::ref(words), std::ref(possibilities), std::ref(patterns), start, end, std::ref(scored_words), std::ref(freqMap));
}
// Wait for all threads to finish.
for (auto& t : threads) {
t.join();
}
// Sort scored words in descending order based on score.
std::sort(scored_words.begin(), scored_words.end(),
[&possibilities, &freqMap](const std::pair<double, std::string>& a, const std::pair<double, std::string>& b) {
if (a.first != b.first) {
return a.first > b.first; // Sort by score descending
}
// Tiebreaker based on index in possibilities
bool a_posib = (std::find(possibilities.begin(), possibilities.end(), a.second) != possibilities.end());
bool b_posib = (std::find(possibilities.begin(), possibilities.end(), b.second) != possibilities.end());
if(a_posib && b_posib){
return freqMap[a.second] > freqMap[b.second];
}
return a_posib && !b_posib;
});
int num_recs = std::min(10, static_cast<int>(possibilities.size()));
// Display the top 10 recommended guesses based on the scores.
std::cout << "Top " << num_recs << " recommendations for your guess are:\n";
int count = 0;
for (const auto& [score, word] : scored_words) {
std::cout << word;
if(std::find(possibilities.begin(), possibilities.end(), word) != possibilities.end()){std::cout<<"*";}
std::cout << " Score: " << score << "\n";
if (++count == num_recs) break;
}
if(possibilities.size() < 10000){
std::cout << "\nPossible Words: \n";
for(const auto& pos : possibilities){
std::cout << pos << ": Estimated Liklihood " << freqMap[pos] << "\n";
}
}
std::cout << "\n";
++guess_num; // Increment guess counter.
}
// Congratulate the user on finding the correct word.
std::cout << "\nCongrats, you got it in " << guess_num << " guesses!";
return 0;
}