ordle/ordle.h

214 lines
7.1 KiB
C
Raw Normal View History

2024-12-14 14:14:40 +01:00
#ifndef ORDLE_H
#define ORDLE_H
#include <algorithm>
2024-12-14 14:14:40 +01:00
#include <iostream>
#include <map>
#include <string>
2024-12-14 14:14:40 +01:00
#include <tuple>
#include <vector>
// TODO: Evaluate need for helpers
2024-12-14 14:14:40 +01:00
// Helper types and aliases
using size_type = std::string::size_type;
/**
* @brief A mapping of indices to letters or strings.
*
* This type alias represents a map where each key is a position (index), and
* the value is a string (typically a single letter). It is used to track the
* correct or misplaced letter positions in word-guessing games, like Wordle, or
* similar puzzles.
*
* @note The `std::map` ensures that the indices are stored in sorted order,
* which is useful for efficiently checking conditions related to the positions
* of letters within words.
*
* @see correct_fn, misplaced_fn, build_list
*/
2024-12-26 19:34:21 +01:00
using IndexMap = std::map<size_type, char>;
/**
* Reads a list of words from an input stream where each word is separated by a
* newline.
*
* @param input The input stream containing newline-separated words.
* @return A vector containing all the words from the input stream.
*/
2024-12-14 14:14:40 +01:00
std::vector<std::string> read_candidates(std::istream &input);
/**
* Checks if a string contains any character from a given set of characters.
*
* @param s The string to search within.
* @param cs A string containing the set of characters to look for.
* @return true if any character in 'cs' is found in 's'; otherwise, false.
*/
inline 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; });
}
/**
* Checks if a string contains a specific character at a given position.
*
* @param s The string to search within.
* @param c The character to check for.
* @param pos The position to check within the string.
* @return true if the character 'c' is found at position 'pos' in the string
* 's'; otherwise, false.
*/
inline bool contains_at(const std::string &s, char c, size_type pos) {
return pos < s.size() && s[pos] == c;
}
2024-12-14 14:14:40 +01:00
/**
* Checks if a string contains a specific character, but not at a given
* position.
*
* @param s The string to search within.
* @param c The character to check for.
* @param pos The position where the character must not be located.
* @return true if the character 'c' is found in the string 's' and not at
* position 'pos'; otherwise, false.
*/
inline bool contains_but_not_at(const std::string &s, char c, size_type pos) {
for (size_type i = 0; i < s.size(); ++i) {
if (s[i] == c && i != pos) {
return true; // Found letter but not at the correct position
}
}
return false; // Letter not found or in the correct index
}
/**
* A functor to filter words containing any of the specified letters.
*/
2024-12-14 14:14:40 +01:00
struct wrong_fn {
/**
* Constructs a functor with the specified letters to filter against.
*
* @param letters A string containing the letters that words should not
* contain.
*/
2024-12-26 19:34:21 +01:00
wrong_fn(const std::string &letters) : letter_set{letters} {}
/**
* Checks if a word contains any of the specified "wrong" letters.
*
* @param word The word to be checked.
* @return True if the word contains any "wrong" letters; false otherwise.
*/
2024-12-14 14:14:40 +01:00
bool operator()(const std::string &word) const;
private:
2024-12-26 19:34:21 +01:00
std::string letter_set; ///< The letters considered "wrong".
2024-12-14 14:14:40 +01:00
};
/**
* A functor to filter words based on exact character positions.
*/
2024-12-14 14:14:40 +01:00
struct correct_fn {
/**
* Constructs a functor with the specified indices and characters.
*
* @param idxs A map of indices to characters representing the exact
* matches.
*/
2024-12-26 19:34:21 +01:00
correct_fn(const IndexMap &idxs) : map{idxs} {}
/**
* Checks if a word contains the correct characters at the specified
* indices.
*
* @param word The word to be checked.
* @return True if the word matches the correct indices; false otherwise.
*/
2024-12-14 14:14:40 +01:00
bool operator()(const std::string &word) const;
private:
2024-12-26 19:34:21 +01:00
IndexMap map; ///< Map of indices to expected characters.
2024-12-14 14:14:40 +01:00
};
/**
* A functor to filter words based on misplaced characters.
*/
2024-12-14 14:14:40 +01:00
struct misplaced_fn {
/**
* Constructs a functor with the specified indices and characters.
*
* @param idxs A map of indices to characters representing misplaced
* matches.
*/
2024-12-26 19:34:21 +01:00
misplaced_fn(const IndexMap &idxs) : map{idxs} {}
/**
* Checks if a word contains the specified characters but at incorrect
* positions.
*
* @param word The word to be checked.
2024-12-26 19:34:21 +01:00
* @return True if the word contains ALL of the characters but at incorrect
* positions; false otherwise.
*/
2024-12-14 14:14:40 +01:00
bool operator()(const std::string &word) const;
private:
2024-12-26 19:34:21 +01:00
IndexMap map; ///< Map of indices to misplaced characters.
2024-12-14 14:14:40 +01:00
};
/**
* Filters the `candidates` list by removing words that do not meet certain
* conditions based on the given `wrong`, `green`, and `yellow` parameters.
*
* The conditions are as follows:
* - A word is removed if it contains any of the incorrect letters specified in
* `wrong`.
* - A word is removed if it does not match the positions of the letters
* specified in `green` (green letters must be in the exact same positions).
* - A word is removed if it does not correctly place the yellow letters
* specified in `yellow` (yellow letters must be in the word but at different
* positions).
*
* @param candidates A reference to the vector of candidate words to filter.
* @param wrong A string of incorrect letters that should not appear in the
* word.
* @param green An `IndexMap` representing the correct letters and their exact
* positions in the word.
* @param yellow An `IndexMap` representing the letters that should appear in
* the word but in incorrect positions.
*/
2024-12-14 14:14:40 +01:00
void do_filter(std::vector<std::string> &candidates, const std::string &wrong,
const IndexMap &green, const IndexMap &yellow);
/**
* Constructs an `IndexMap` from the provided string.
* The function parses the string and maps the indices of letters to their
* respective positions in a way that is suitable for the filtering logic in the
* Wordle solver.
*
* @param line A string representing the word or feedback line to process (e.g.,
* "G__Y_").
*
* @return An `IndexMap` where the key is the index of the letter, and the value
* represents the status of that letter. This could be an enumeration or an
* integer representing the state of the letter (e.g., green, yellow, or gray).
*/
IndexMap build_list(const std::string &line);
2024-12-14 14:14:40 +01:00
/**
* Prompts the user (or simulation) for input, typically to get a guess and
* feedback from the user. This function returns the guessed word along with its
* green and yellow feedback in the form of `IndexMap`s.
*
* @return A tuple containing three elements:
* - A string representing the guessed word.
* - An `IndexMap` for the positions and letters that are correct (green
* letters).
* - An `IndexMap` for the positions and letters that are in the word
* but misplaced (yellow letters).
*/
std::tuple<std::string, IndexMap, IndexMap> prompt();
2024-12-14 14:14:40 +01:00
#endif // ORDLE_H