213 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			213 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef ORDLE_H
 | |
| #define ORDLE_H
 | |
| 
 | |
| #include <algorithm>
 | |
| #include <iostream>
 | |
| #include <map>
 | |
| #include <string>
 | |
| #include <tuple>
 | |
| #include <vector>
 | |
| 
 | |
| // TODO: Evaluate need for helpers
 | |
| 
 | |
| // 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
 | |
|  */
 | |
| 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.
 | |
|  */
 | |
| 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;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * 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.
 | |
|  */
 | |
| 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.
 | |
|      */
 | |
|     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.
 | |
|      */
 | |
|     bool operator()(const std::string &word) const;
 | |
| 
 | |
|   private:
 | |
|     std::string letter_set; ///< The letters considered "wrong".
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * A functor to filter words based on exact character positions.
 | |
|  */
 | |
| struct correct_fn {
 | |
|     /**
 | |
|      * Constructs a functor with the specified indices and characters.
 | |
|      *
 | |
|      * @param idxs A map of indices to characters representing the exact
 | |
|      * matches.
 | |
|      */
 | |
|     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.
 | |
|      */
 | |
|     bool operator()(const std::string &word) const;
 | |
| 
 | |
|   private:
 | |
|     IndexMap map; ///< Map of indices to expected characters.
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * A functor to filter words based on misplaced characters.
 | |
|  */
 | |
| struct misplaced_fn {
 | |
|     /**
 | |
|      * Constructs a functor with the specified indices and characters.
 | |
|      *
 | |
|      * @param idxs A map of indices to characters representing misplaced
 | |
|      * matches.
 | |
|      */
 | |
|     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.
 | |
|      * @return True if the word contains ALL of the characters but at incorrect
 | |
|      * positions; false otherwise.
 | |
|      */
 | |
|     bool operator()(const std::string &word) const;
 | |
| 
 | |
|   private:
 | |
|     IndexMap map; ///< Map of indices to misplaced characters.
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * 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.
 | |
|  */
 | |
| 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);
 | |
| 
 | |
| /**
 | |
|  * 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();
 | |
| 
 | |
| #endif // ORDLE_H
 | 
