Spaces:
Sleeping
Sleeping
File size: 9,271 Bytes
c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 62e140b c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 c5bcf4c 28f1794 |
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 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
import gradio as gr
import re
from collections import defaultdict
# --- Core Wordle Solver Logic ---
def load_words():
"""Load 5-letter words from the words.txt file."""
words = []
try:
with open('words.txt', 'r') as f:
for line in f:
word = line.strip().lower()
if len(word) == 5 and word.isalpha():
words.append(word)
except FileNotFoundError:
print("FATAL ERROR: words.txt not found. Please create it in the same directory.")
return None
return words
WORD_LIST = load_words()
# --- Advanced Parsing Logic (to handle flexible input) ---
def parse_guess(line):
"""Parse a single line of a guess, like 'π₯ π¨ π₯ π₯ π© πππ‘ππ' or 'IRATE π¨π₯π¨π₯π©'."""
# Mapping for special bold characters to regular ASCII
math_bold_to_regular = {
'π': 'A', 'π': 'B', 'π': 'C', 'π': 'D', 'π': 'E', 'π': 'F', 'π': 'G', 'π': 'H',
'π': 'I', 'π': 'J', 'π': 'K', 'π': 'L', 'π ': 'M', 'π‘': 'N', 'π’': 'O', 'π£': 'P',
'π€': 'Q', 'π₯': 'R', 'π¦': 'S', 'π§': 'T', 'π¨': 'U', 'π©': 'V', 'πͺ': 'W', 'π«': 'X',
'π¬': 'Y', 'π': 'Z'
}
def convert_math_bold_to_regular(text):
return ''.join(math_bold_to_regular.get(char, char) for char in text)
line = convert_math_bold_to_regular(line.upper())
# Pattern 1: Emojis first, then word (e.g., π₯ π¨ ... π© HINGE)
pattern1 = r'([\s]*[π₯π¨π©β¬][\s]*){5}([\s]*[A-Z]{5})'
match1 = re.search(pattern1, line)
if match1:
emojis = re.sub(r'\s+', '', match1.group(0).replace(match1.group(2).strip(), ''))
word = match1.group(2).strip().lower()
return word, emojis
# Pattern 2: Word first, then emojis (e.g., HINGE π₯ π¨ ... π©)
pattern2 = r'([A-Z]{5}[\s]*)'
match2 = re.search(pattern2, line)
if match2:
word = match2.group(1).strip().lower()
emojis = re.sub(r'\s+', '', line.replace(match2.group(1), ''))
if len(emojis) == 5:
return word, emojis
return None, None
def parse_multiline_input(raw_text):
"""Parses a multi-line string of guesses into a list of clues."""
clues = []
errors = []
for i, line in enumerate(raw_text.strip().split('\n'), 1):
if not line.strip():
continue
word, emojis = parse_guess(line)
if word and emojis and len(word) == 5 and len(emojis) == 5:
clues.append((word, emojis))
else:
errors.append(f"Line {i}: Could not parse -> '{line}'")
return clues, errors
# --- Core Filtering and Suggestion Logic (Unchanged) ---
def word_matches_clue(word, guess_word, emoji_result):
for i, (guess_char, emoji) in enumerate(zip(guess_word, emoji_result)):
if emoji == 'π©' and word[i] != guess_char: return False
for i, (guess_char, emoji) in enumerate(zip(guess_word, emoji_result)):
if emoji == 'π¨' and (guess_char not in word or word[i] == guess_char): return False
for i, (guess_char, emoji) in enumerate(zip(guess_word, emoji_result)):
if emoji in ['π₯', 'β¬']:
clue_count = sum(1 for j, gc in enumerate(guess_word) if gc == guess_char and emoji_result[j] in ['π©', 'π¨'])
if word.count(guess_char) > clue_count: return False
return True
def filter_words_by_clues(words, clues):
if not clues: return words
remaining = list(words)
for guess, emoji in clues:
remaining = [w for w in remaining if word_matches_clue(w, guess, emoji)]
return remaining
def get_letter_frequency(words):
freq = defaultdict(int)
for word in words:
for char in set(word): freq[char] += 1
return freq
def score_word(word, letter_freq):
return sum(letter_freq[char] for char in set(word))
def get_best_guess(words, all_words):
if not words: return None, "No words match the clues."
if len(words) <= 2: return words[0], f"{len(words)} possible word(s) remain."
letter_freq = get_letter_frequency(words)
best_word = max(all_words, key=lambda w: score_word(w, letter_freq))
return best_word, f"{len(words)} possible words remain."
# --- Gradio Interface Functions ---
def process_guesses(raw_text_input):
"""Handles the 'Submit Guesses' button click."""
parsed_clues, errors = parse_multiline_input(raw_text_input)
if errors:
error_msg = "\n".join(errors)
history_md = format_clues_history([])
return [], gr.update(visible=True, value=error_msg), "", "Parsing Error", history_md
if not parsed_clues:
error_msg = "Input is empty or invalid. Please check the format."
history_md = format_clues_history([])
return [], gr.update(visible=True, value=error_msg), "", "Invalid Input", history_md
remaining_words = filter_words_by_clues(WORD_LIST, parsed_clues)
best_guess, status_text = get_best_guess(remaining_words, WORD_LIST)
history_md = format_clues_history(parsed_clues)
if not remaining_words:
best_guess_str = "π"
status_text = "No words match your clues. Check for typos and try again."
elif len(remaining_words) == 1:
best_guess_str = remaining_words[0].upper()
status_text = "π Found it! This is the only possible word."
else:
best_guess_str = best_guess.upper()
return parsed_clues, gr.update(visible=False, value=""), best_guess_str, status_text, history_md
def get_other_suggestions(current_clues_list):
"""Provides alternative word suggestions based on the current parsed clues."""
if not current_clues_list:
return "Enter at least one guess to get suggestions."
remaining_words = filter_words_by_clues(WORD_LIST, current_clues_list)
if not remaining_words: return "No words match the current clues."
if len(remaining_words) == 1: return f"Only one word remains: **{remaining_words[0].upper()}**"
letter_freq = get_letter_frequency(remaining_words)
scored_words = sorted([(word, score_word(word, letter_freq)) for word in remaining_words], key=lambda x: x[1], reverse=True)
suggestions_md = f"### Top Suggestions ({len(remaining_words)} words remain)\n"
suggestions_md += "\n".join([f"- **{word.upper()}**" for word, _ in scored_words[:10]])
if len(scored_words) > 10:
suggestions_md += f"\n\n...and {len(scored_words) - 10} more."
return suggestions_md
def reset_session():
"""Clears all inputs, outputs, and the session state."""
return [], "", "", "", "No guesses yet. Enter your game history above.", "", gr.update(visible=False, value="")
def format_clues_history(clues_list):
"""Converts the list of clues into a markdown string for display."""
if not clues_list:
return "No guesses yet. Enter your game history above."
md = "### Your Parsed Guesses\n"
for word, emojis in clues_list:
md += f"- `{word.upper()}` -> {emojis}\n"
return md
# --- Gradio UI Layout ---
with gr.Blocks(theme=gr.themes.Soft(), title="Wordle Solver Bot") as demo:
session_clues = gr.State([])
gr.Markdown("# π§© Wordle Solver Bot (Single Input)")
gr.Markdown("Paste your entire game history into the text box below. Each line should contain one guess and its results.")
#[Image of a Wordle game grid]
with gr.Row():
with gr.Column(scale=2):
guesses_input = gr.Textbox(
label="Enter Guesses (One Per Line)",
lines=5,
placeholder="Example:\nπ₯ π¨ π₯ π₯ π© HINGE\nπ¨ π₯ π¨ π₯ π© IRATE\n..."
)
error_box = gr.Textbox(label="Error", visible=False, interactive=False, lines=3)
with gr.Row():
submit_button = gr.Button("Find Best Guess", variant="primary")
other_button = gr.Button("Get Other Suggestions")
reset_button = gr.Button("Reset Session", variant="stop")
with gr.Column(scale=3):
best_guess_output = gr.Textbox(label="π‘ Best Next Guess", interactive=False)
status_output = gr.Textbox(label="π Status", interactive=False)
with gr.Row():
history_output = gr.Markdown("No guesses yet. Enter your game history above.")
other_suggestions_output = gr.Markdown("")
# --- Event Handlers ---
submit_button.click(
fn=process_guesses,
inputs=[guesses_input],
outputs=[session_clues, error_box, best_guess_output, status_output, history_output]
)
other_button.click(
fn=get_other_suggestions,
inputs=[session_clues],
outputs=[other_suggestions_output]
)
reset_button.click(
fn=reset_session,
inputs=[],
outputs=[session_clues, guesses_input, best_guess_output, status_output, history_output, other_suggestions_output, error_box]
)
if __name__ == "__main__":
if not WORD_LIST:
print("Could not start the application because 'words.txt' is missing or empty.")
else:
print("Starting Gradio app... Access it at the URL provided below.")
demo.launch()
|