Source code for src.modules.backend.solver.stateless_solver_strategy

# src/modules/backend/solver/stateless_solver_strategy.py
"""
Stateless strategy pattern implementation for Wordle solver algorithms.
"""
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, List, Optional, Set, Tuple

if TYPE_CHECKING:
    from src.modules.backend.legacy_word_manager import WordManager
    from src.modules.backend.stateless_word_manager import StatelessWordManager


[docs] class StatelessSolverStrategy(ABC): """Abstract base class for stateless Wordle solver strategies."""
[docs] @abstractmethod def get_top_suggestions( self, constraints: List[Tuple[str, str]], count: int = 10, word_manager: Optional["WordManager"] = None, stateless_word_manager: Optional["StatelessWordManager"] = None, prefer_common: bool = True, word_set: Optional[Set[str]] = None, ) -> List[str]: """ Get top N suggestions based on the strategy's algorithm using stateless filtering. Args: constraints: List of (guess, result) tuples representing game constraints count: Number of suggestions to return word_manager: Optional WordManager instance for backward compatibility stateless_word_manager: Optional StatelessWordManager for pure stateless operations prefer_common: Whether to prefer common words in suggestions word_set: Optional specific set of words to consider. If None, uses all words. Returns: List of suggested words, ordered by preference """ raise NotImplementedError("Subclasses must implement get_top_suggestions")
def _get_filtered_words( self, constraints: List[Tuple[str, str]], word_manager: Optional["WordManager"] = None, stateless_word_manager: Optional["StatelessWordManager"] = None, word_set: Optional[Set[str]] = None, ) -> Tuple[List[str], List[str]]: """ Get filtered possible and common words using stateless filtering. Args: constraints: List of (guess, result) tuples word_manager: Optional WordManager for backward compatibility stateless_word_manager: Optional StatelessWordManager word_set: Optional specific set of words to filter Returns: Tuple of (possible_words, common_words) """ if stateless_word_manager is not None: # Use pure stateless manager possible_words = stateless_word_manager.apply_multiple_constraints( constraints, word_set ) common_words = stateless_word_manager.get_common_words_from_set( set(possible_words) ) elif word_manager is not None: # Use stateless methods on existing word manager possible_words = word_manager.apply_multiple_constraints( constraints, word_set ) common_words = [ word for word in possible_words if word in word_manager.common_words ] else: raise ValueError( "Either word_manager or stateless_word_manager must be provided" ) return possible_words, common_words def _get_word_frequency( self, word: str, word_manager: Optional["WordManager"] = None, stateless_word_manager: Optional["StatelessWordManager"] = None, ) -> int: """Get word frequency using available word manager.""" if stateless_word_manager is not None: return stateless_word_manager.get_word_frequency(word) elif word_manager is not None: return word_manager.get_word_frequency(word) else: return 0 def _get_word_entropy( self, word: str, word_manager: Optional["WordManager"] = None, stateless_word_manager: Optional["StatelessWordManager"] = None, ) -> float: """Get word entropy using available word manager.""" if stateless_word_manager is not None: return stateless_word_manager.get_word_entropy(word) elif word_manager is not None: return word_manager.get_word_entropy(word) else: return 0.0
class LegacyStrategyAdapter: """Adapter to make legacy strategies work with stateless interface.""" def __init__(self, legacy_strategy): """Initialize with a legacy strategy instance.""" self.legacy_strategy = legacy_strategy def get_top_suggestions( self, constraints: List[Tuple[str, str]], count: int = 10, word_manager: Optional["WordManager"] = None, stateless_word_manager: Optional["StatelessWordManager"] = None, prefer_common: bool = True, word_set: Optional[Set[str]] = None, ) -> List[str]: """ Adapt legacy strategy to work with stateless interface. This allows legacy strategies to work with the new stateless interface while we incrementally migrate them. """ # Get filtered words using stateless methods if stateless_word_manager is not None: possible_words = stateless_word_manager.apply_multiple_constraints( constraints, word_set ) common_words = stateless_word_manager.get_common_words_from_set( set(possible_words) ) wm = None # Legacy strategies can work without word manager elif word_manager is not None: possible_words = word_manager.apply_multiple_constraints( constraints, word_set ) common_words = [ word for word in possible_words if word in word_manager.common_words ] wm = word_manager else: raise ValueError( "Either word_manager or stateless_word_manager must be provided" ) # Detect if legacy_strategy is actually a stateless strategy if ( hasattr(self.legacy_strategy, "__class__") and "Stateless" in self.legacy_strategy.__class__.__name__ ): # Call using stateless interface return self.legacy_strategy.get_top_suggestions( constraints=constraints, count=count, word_manager=word_manager, stateless_word_manager=stateless_word_manager, prefer_common=prefer_common, word_set=set(possible_words) if possible_words else word_set, ) else: # Call using legacy interface try: return self.legacy_strategy.get_top_suggestions( count=count, word_manager=wm, possible_words=possible_words, common_words=common_words, guesses_so_far=constraints, ) except TypeError: # Try with fewer parameters if full call fails try: return self.legacy_strategy.get_top_suggestions( count=count, word_manager=wm ) except TypeError: # Last resort - just use the count parameter return self.legacy_strategy.get_top_suggestions(count)