Compare commits
2 commits
b542c22bc2
...
17944c4d42
Author | SHA1 | Date | |
---|---|---|---|
|
17944c4d42 | ||
|
64c47c753b |
3 changed files with 222 additions and 1 deletions
44
main.cc
44
main.cc
|
@ -1,3 +1,45 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "ordle.h"
|
||||
|
||||
int main(int argc, char *argv[]) { std::cout << "Hello, ordle!" << std::endl; }
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " <wordlist file>\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::ifstream file(argv[1]);
|
||||
if (!file) {
|
||||
std::cerr << "Could not open file: " << argv[1] << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto candidates = read_candidates(file);
|
||||
std::string wrong;
|
||||
letters_and_indices green, yellow;
|
||||
|
||||
while (!candidates.empty()) {
|
||||
std::cout << "Remaining candidates: \n";
|
||||
for (const auto &word : candidates) {
|
||||
std::cout << word << " ";
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
|
||||
auto [new_wrong, new_green, new_yellow] = prompt();
|
||||
wrong.append(new_wrong);
|
||||
green.insert(new_green.begin(), new_green.end());
|
||||
yellow.insert(new_yellow.begin(), new_yellow.end());
|
||||
|
||||
do_filter(candidates, wrong, green, yellow);
|
||||
|
||||
if (candidates.size() <= 1) break;
|
||||
}
|
||||
|
||||
if (candidates.empty()) {
|
||||
std::cout << "No solution found.\n";
|
||||
} else {
|
||||
std::cout << "Solution: " << candidates.front() << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
125
ordle.cc
Normal file
125
ordle.cc
Normal file
|
@ -0,0 +1,125 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
// Helper types and aliases
|
||||
using size_type = std::string::size_type;
|
||||
using letters_and_indices = std::map<size_type, std::string>;
|
||||
|
||||
// Function to read candidates from a file
|
||||
std::vector<std::string> read_candidates(std::istream &input) {
|
||||
std::vector<std::string> candidates;
|
||||
std::string word;
|
||||
|
||||
while (input >> word) {
|
||||
if (word.size() == 5) {
|
||||
std::transform(word.begin(), word.end(), word.begin(), ::tolower);
|
||||
candidates.push_back(word);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove duplicates
|
||||
std::sort(candidates.begin(), candidates.end());
|
||||
candidates.erase(std::unique(candidates.begin(), candidates.end()), candidates.end());
|
||||
|
||||
return candidates;
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
bool contains_any_of(const std::string &s, const std::string &cs) {
|
||||
return std::any_of(cs.begin(), cs.end(), [&s](char c) { return s.find(c) != std::string::npos; });
|
||||
}
|
||||
|
||||
bool contains_at(const std::string &s, char c, size_type pos) {
|
||||
return pos < s.size() && s[pos] == c;
|
||||
}
|
||||
|
||||
bool contains_but_not_at(const std::string &s, char c, size_type pos) {
|
||||
return s.find(c) != std::string::npos && !contains_at(s, c, pos);
|
||||
}
|
||||
|
||||
// Functor for wrong letters
|
||||
struct wrong_fn {
|
||||
explicit wrong_fn(const std::string &letters) : l{letters} {}
|
||||
|
||||
bool operator()(const std::string &word) const {
|
||||
return contains_any_of(word, l);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string l;
|
||||
};
|
||||
|
||||
// Functor for correct letters
|
||||
struct correct_fn {
|
||||
explicit correct_fn(const letters_and_indices &idxs) : m{idxs} {}
|
||||
|
||||
bool operator()(const std::string &word) const {
|
||||
return std::all_of(m.begin(), m.end(), [&word](const auto &pair) {
|
||||
return contains_at(word, pair.second[0], pair.first);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
letters_and_indices m;
|
||||
};
|
||||
|
||||
// Functor for misplaced letters
|
||||
struct misplaced_fn {
|
||||
explicit misplaced_fn(const letters_and_indices &idxs) : m{idxs} {}
|
||||
|
||||
bool operator()(const std::string &word) const {
|
||||
return std::all_of(m.begin(), m.end(), [&word](const auto &pair) {
|
||||
return contains_but_not_at(word, pair.second[0], pair.first);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
letters_and_indices m;
|
||||
};
|
||||
|
||||
// Function to filter candidates
|
||||
void do_filter(std::vector<std::string> &candidates, const std::string &wrong,
|
||||
const letters_and_indices &green, const letters_and_indices &yellow) {
|
||||
auto predicate = [&wrong, &green, &yellow](const std::string &word) {
|
||||
return wrong_fn(wrong)(word) || !correct_fn(green)(word) || !misplaced_fn(yellow)(word);
|
||||
};
|
||||
|
||||
candidates.erase(std::remove_if(candidates.begin(), candidates.end(), predicate), candidates.end());
|
||||
}
|
||||
|
||||
// User interaction function
|
||||
letters_and_indices build_list(const std::string &line) {
|
||||
std::istringstream iss(line);
|
||||
letters_and_indices result;
|
||||
char letter;
|
||||
size_type index;
|
||||
|
||||
while (iss >> letter >> index) {
|
||||
result[index] = std::string(1, letter);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<std::string, letters_and_indices, letters_and_indices> prompt() {
|
||||
std::string wrong;
|
||||
std::cout << "Enter wrong letters:\n";
|
||||
std::getline(std::cin, wrong);
|
||||
|
||||
std::string correct;
|
||||
std::cout << "Enter correct letters (letter index)*:\n";
|
||||
std::getline(std::cin, correct);
|
||||
auto green = build_list(correct);
|
||||
|
||||
std::string misplaced;
|
||||
std::cout << "Enter misplaced letters (letter index)*:\n";
|
||||
std::getline(std::cin, misplaced);
|
||||
auto yellow = build_list(misplaced);
|
||||
|
||||
return {wrong, green, yellow};
|
||||
}
|
54
ordle.h
Normal file
54
ordle.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
#ifndef ORDLE_H
|
||||
#define ORDLE_H
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <tuple>
|
||||
|
||||
// Helper types and aliases
|
||||
using size_type = std::string::size_type;
|
||||
using letters_and_indices = std::map<size_type, std::string>;
|
||||
|
||||
// Function declarations
|
||||
std::vector<std::string> read_candidates(std::istream &input);
|
||||
|
||||
bool contains_any_of(const std::string &s, const std::string &cs);
|
||||
bool contains_at(const std::string &s, char c, size_type pos);
|
||||
bool contains_but_not_at(const std::string &s, char c, size_type pos);
|
||||
|
||||
// Functors
|
||||
struct wrong_fn {
|
||||
explicit wrong_fn(const std::string &letters);
|
||||
bool operator()(const std::string &word) const;
|
||||
|
||||
private:
|
||||
std::string l;
|
||||
};
|
||||
|
||||
struct correct_fn {
|
||||
explicit correct_fn(const letters_and_indices &idxs);
|
||||
bool operator()(const std::string &word) const;
|
||||
|
||||
private:
|
||||
letters_and_indices m;
|
||||
};
|
||||
|
||||
struct misplaced_fn {
|
||||
explicit misplaced_fn(const letters_and_indices &idxs);
|
||||
bool operator()(const std::string &word) const;
|
||||
|
||||
private:
|
||||
letters_and_indices m;
|
||||
};
|
||||
|
||||
void do_filter(std::vector<std::string> &candidates, const std::string &wrong,
|
||||
const letters_and_indices &green, const letters_and_indices &yellow);
|
||||
|
||||
letters_and_indices build_list(const std::string &line);
|
||||
std::tuple<std::string, letters_and_indices, letters_and_indices> prompt();
|
||||
|
||||
#endif // ORDLE_H
|
Loading…
Reference in a new issue