summaryrefslogtreecommitdiff
path: root/src/solve.py
diff options
context:
space:
mode:
authorleo <azuminha1@gmail.com>2025-09-24 16:41:32 -0300
committerleo <azuminha1@gmail.com>2025-09-24 16:41:32 -0300
commit466b6a8d0935309288e8a34b089d169b9783bcc2 (patch)
tree43299df0d8ddd917a49a0414f947daaad4d9f1a7 /src/solve.py
parentb3efad8d1a4062ccad21ca224af30e0b6e89b9e5 (diff)
terminado
Diffstat (limited to 'src/solve.py')
-rw-r--r--src/solve.py124
1 files changed, 124 insertions, 0 deletions
diff --git a/src/solve.py b/src/solve.py
index fd20c35..d480c0d 100644
--- a/src/solve.py
+++ b/src/solve.py
@@ -1,3 +1,7 @@
+import math
+import threading
+from collections import Counter
+
from enum import Enum
@@ -8,11 +12,27 @@ class LetterState(Enum):
NONE = "NONE"
+class PatternState(Enum):
+ GREEN = "GREEN"
+ YELLOW = "YELLOW"
+ GRAY = "GRAY"
+
+
+class Pattern:
+ def __init__(self, states):
+ assert (len(states) == 5)
+ self.states = states
+
+ def __repr__(self):
+ return f"{self.states[0]} {self.states[1]} {self.states[2]} {self.states[3]} {self.states[4]}"
+
+
class Letter:
def __init__(self, char, position=-1, state=LetterState.NONE):
self.char = char.upper()
self.position = position
self.state = state
+ self.possible_positions = [0, 1, 2, 3, 4]
def __repr__(self):
return f"Letter(char='{self.char}', position={self.position}, state={self.state.name})"
@@ -39,5 +59,109 @@ with open('../data/words.txt', 'r') as file:
for word in file:
words.append(Word(word.strip(), 0))
+patterns = []
+patterns_size = 3**5
+for i in range(0, patterns_size):
+ tmp = i
+ p = [PatternState.GREEN] * 5
+ for j in range(0, 5):
+ if tmp % 3 == 2:
+ p[j] = PatternState.GREEN
+ if tmp % 3 == 1:
+ p[j] = PatternState.YELLOW
+ if tmp % 3 == 0:
+ p[j] = PatternState.GRAY
+ tmp = tmp // 3
+ patterns.append(Pattern(p))
+ # print(patterns[i])
+
+
############## TUDO INICIALIZADO #################################
# calcular a entropia, e pegar a palavra que da mais informacao
+# pi = probabilidade do padrao i dado a palavra x
+# -sum(pi * log2(pi))
+
+
+def get_pattern_given_answer(guess, answer):
+ pattern = [PatternState.GRAY] * 5
+ used = [False] * 5
+
+ for i in range(5):
+ if guess[i] == answer[i]:
+ pattern[i] = PatternState.GREEN
+ used[i] = True
+
+ for i in range(5):
+ if pattern[i] == PatternState.GREEN:
+ continue
+
+ for j in range(5):
+ if not used[j] and guess[i] == answer[j]:
+ pattern[i] = PatternState.YELLOW
+ used[j] = True
+ break
+
+ return Pattern(pattern)
+
+
+# p(word | pat) = numero de palavras que fazem o padrao pat se eu colocasse word
+# palavras restantes
+def calculate_entropy(word):
+ pattern_freq = Counter()
+ for answer in words:
+ pat = get_pattern_given_answer(word.word, answer.word)
+ pattern_freq[tuple(pat.states)] += 1
+
+ entropy = 0
+ for pat in patterns:
+ pi = pattern_freq[tuple(pat.states)] / len(words)
+ if pi == 0:
+ continue
+ entropy += pi * math.log2(pi)
+
+ return -entropy
+
+
+def parse_pattern(pattern_input):
+ ret_pat = [PatternState.GRAY] * 5
+
+ for i in range(5):
+ if (pattern_input[i] == 'G'):
+ ret_pat[i] = PatternState.GREEN
+ if (pattern_input[i] == 'Y'):
+ ret_pat[i] = PatternState.YELLOW
+ if (pattern_input[i] == 'B'):
+ ret_pat[i] = PatternState.GRAY
+
+ return Pattern(ret_pat)
+
+
+def filter_words(words, guess, pattern):
+ ret = []
+ for w in words:
+ if (get_pattern_given_answer(guess.word, w.word).states == pattern.states):
+ ret.append(w)
+ return ret
+
+
+while (len(words) > 1):
+ print(f"size: {len(words)}")
+
+ for word in words:
+ entropy = calculate_entropy(word)
+ word.self_info = entropy
+ # print(f"word {word.word}, entropy: {entropy}")
+
+ words.sort(key=lambda w: w.self_info, reverse=True)
+ for w in words[:15]:
+ print(w)
+
+ # update words
+ guess_input = input("Enter your guess word: ").strip().lower()
+ pattern_input = input("Enter the resulting pattern (G/Y/B): ").strip()
+ assert (len(pattern_input) == 5)
+
+ pattern = parse_pattern(pattern_input)
+ words = filter_words(words, Word(guess_input, 0), pattern)
+
+print(words[0])