Reshinth Adithyan commited on
Commit
c5f913a
·
1 Parent(s): 314fe3a

Initial Commit

Browse files
Files changed (7) hide show
  1. app.py +17 -0
  2. requirements.txt +3 -0
  3. src/__init__.py +0 -0
  4. src/agent.py +34 -0
  5. src/game.py +99 -0
  6. src/metrics.py +45 -0
  7. src/utils.py +43 -0
app.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ from src.game import Wordle
4
+
5
+
6
+ st.title("WORDLE")
7
+
8
+
9
+ with st.form("Wordle"):
10
+ button = st.form_submit_button("Play")
11
+ box = st.selectbox("Select the trial level :",["6","100"])
12
+ if button:
13
+ wordle = Wordle(int(box))
14
+ chosen_word,game_diction = wordle.play()
15
+ st.dataframe(pd.DataFrame.from_dict(game_diction))
16
+ st.write(f"The actual word is : {wordle.wordle}")
17
+ st.write(f"It took {len(game_diction['step_no'])} random search steps to find it")
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ nltk==3.6.2
2
+ pandas==1.3.0
3
+ streamlit==0.84.0
src/__init__.py ADDED
File without changes
src/agent.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+ from src.metrics import get_word_list
3
+
4
+
5
+ class Cerebrum:
6
+ def __init__(self,vowel_knowledge:int=2) -> None:
7
+ self.word_list = get_word_list()
8
+ self.init_word_list = self.get_vowelled_word_list(vowel_knowledge)
9
+
10
+ def get_vowelled_word_list(self,nos_vowels:int)->list:
11
+ """
12
+ Returns a list of words with the given number of vowels.
13
+ """
14
+ vowels = set(["a","e","i","o","u"])
15
+ tmp_list = []
16
+ for word in self.word_list:
17
+ ind_word_set = set(list(word))
18
+ if len(list(vowels.intersection(ind_word_set))) > nos_vowels:
19
+ tmp_list.append(word)
20
+ return tmp_list
21
+
22
+ def random_first_choice(self)->str:
23
+ return random.choice(self.init_word_list)
24
+
25
+ def random_n_choice(self,hash_output:list[list])->str:
26
+ if len(hash_output) == 1:
27
+ return random.choice(hash_output[0])
28
+ else:
29
+ sub_hash = random.choice(hash_output)
30
+ return random.choice(sub_hash)
31
+
32
+ if __name__ == "__main__":
33
+ cerebrum = Cerebrum()
34
+ print(len(cerebrum.init_word_list))
src/game.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from itertools import count
2
+ from src.metrics import get_word_list,Metrics
3
+ import logging
4
+ import random
5
+ from src.utils import WordHash
6
+ from src.agent import Cerebrum
7
+
8
+
9
+ logging.basicConfig(level=logging.INFO)
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+
14
+
15
+
16
+ class Wordle:
17
+ def __init__(self,steps_to_be_tried=6) -> None:
18
+ self.steps = steps_to_be_tried
19
+ self.word_list = get_word_list()
20
+ self.letter_list = list("abcdefghijklmnopqrstuvwxyz")
21
+ self.wordle = random.choice(self.word_list)
22
+ self.sixth_sense = Cerebrum()
23
+ self.hash = WordHash()
24
+ logger.info(f"The Word to be found is {self.wordle}")
25
+ self.evaluator = Metrics()
26
+
27
+ def deduct_vocab(self,score_dict:dict):
28
+ """
29
+ Returns True if the word is present in the vocab.
30
+ """
31
+ for letter in score_dict:
32
+ if score_dict[letter] == 0:
33
+ if letter in self.letter_list:
34
+ del self.letter_list[self.letter_list.index(letter)]
35
+
36
+ def preprocess_pos_word(self,pos_score_dict:dict):
37
+ """
38
+ Flag : G -> Sure, Y -> Probable
39
+ """
40
+ pos_slice_list_g = []
41
+ pos_slice_list_y = []
42
+ for ind in range(len(pos_score_dict)):
43
+ letter = list(pos_score_dict.keys())[ind]
44
+ score = pos_score_dict[letter]
45
+ if score == 2:
46
+ pos_slice_list_g.append([ind,letter,"G"])
47
+ if score == 1:
48
+ for possible_index in range(5):
49
+ if possible_index != ind:
50
+ pos_slice_list_y.append([possible_index,letter,"Y"])
51
+
52
+ return pos_slice_list_g + pos_slice_list_y
53
+
54
+ def single_step(self,pred_word:str):
55
+ pos_score_dict = self.evaluator(self.wordle,pred_word)
56
+ self.deduct_vocab(pos_score_dict)
57
+
58
+ return pos_score_dict
59
+
60
+ def play(self)->str:
61
+ game_diction = {"step_no":[],"chosen_word":[],"status":[]}
62
+ for step in range(self.steps):
63
+ logger.info(f"Step {step}")
64
+ if step == 0:
65
+ chosen = self.sixth_sense.random_first_choice()
66
+ logger.info(f"Chosen word is {chosen}")
67
+ pos_score_dict = self.single_step(chosen)
68
+ slice_pos_list = self.hash.slice_pos(self.preprocess_pos_word(pos_score_dict))
69
+ game_diction["chosen_word"].append(chosen)
70
+ game_diction["step_no"].append(step)
71
+ game_diction["status"].append("CONTINUE")
72
+ else:
73
+
74
+ chosen = self.sixth_sense.random_n_choice(slice_pos_list)
75
+ logger.info(f"Chosen word is {chosen}")
76
+ pos_score_dict = self.single_step(chosen)
77
+ slice_pos_list = self.hash.slice_pos(self.preprocess_pos_word(pos_score_dict))
78
+ game_diction["chosen_word"].append(chosen)
79
+ game_diction["step_no"].append(step)
80
+ if chosen != self.wordle:
81
+ game_diction["status"].append("CONTINUE")
82
+ elif chosen == self.wordle:
83
+ game_diction["status"].append("IMPRESSIVE")
84
+ logger.info(f"The word is {chosen}")
85
+ break
86
+ return chosen,game_diction
87
+
88
+
89
+
90
+
91
+
92
+ if __name__ == "__main__":
93
+ pass
94
+ # pos_score_dict = wordle_module.single_step("cants")
95
+ # print(pos_score_dict)
96
+ # slice_pos_list = wordle_module.preprocess_pos_word(pos_score_dict)
97
+ # print(slice_pos_list)
98
+ # hash = WordHash()
99
+ # print(hash.slice_pos(slice_pos_list))
src/metrics.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from nltk import corpus
2
+
3
+
4
+ def get_word_list()->list:
5
+
6
+ return [ i for i in corpus.words.words() if len(i) == 5]
7
+
8
+
9
+
10
+ class Metrics:
11
+ def __init__(self):
12
+ self.score_dict = {
13
+ "not_present" : 0,
14
+ "wrong_pos" : 1,
15
+ "right" : 2
16
+ }
17
+ self.word_list = get_word_list()
18
+
19
+ def check_word(self,ref_word:str)->bool:
20
+ """
21
+ Returns True/False based on it's presence.
22
+ """
23
+ return ref_word in self.word_list
24
+
25
+ def __call__(self,ref_word:str,pred_word:str)->dict:
26
+ """
27
+ Returns the position level score based on the comparison
28
+ """
29
+ score_dict = {}
30
+
31
+ for letter_idx in range(5):
32
+ pred_letter = pred_word[letter_idx]
33
+ if pred_letter == ref_word[letter_idx]:
34
+ score_dict[pred_letter] = 2
35
+ elif pred_letter in ref_word:
36
+ score_dict[pred_letter] = 1
37
+ else:
38
+ score_dict[pred_letter] = 0
39
+
40
+ return score_dict
41
+
42
+ if __name__ == "__main__":
43
+ print(len(get_word_list()))
44
+ metric = Metrics()
45
+ print(metric("apple","aplep"))
src/utils.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from itertools import count
2
+ from src.metrics import get_word_list,Metrics
3
+
4
+ import logging
5
+ import random
6
+ logging.basicConfig(level=logging.INFO)
7
+ logger = logging.getLogger(__name__)
8
+
9
+
10
+
11
+ class WordHash:
12
+ def __init__(self) -> None:
13
+ self.word_list = get_word_list()
14
+
15
+ def slice_pos(self,pos_letter_pair_list:list)->list:
16
+ counter = 0
17
+ tmp = []
18
+ tmp_super_list = []
19
+ for pos_letter_pair in pos_letter_pair_list:
20
+ pos,letter,flag = pos_letter_pair[0],pos_letter_pair[1],pos_letter_pair[2]
21
+ if flag == "G":
22
+ if counter == 0:
23
+ for word in self.word_list:
24
+ if word[pos] == letter:
25
+ tmp.append(word)
26
+ else:
27
+ tmp = [word for word in tmp if word[pos] == letter]
28
+ counter = counter + 1
29
+ else:
30
+ tmp_super_list.append(tmp)
31
+ if counter == 0:
32
+ for word in self.word_list:
33
+ if word[pos] == letter:
34
+ tmp_super_list[-1].append(word)
35
+ else:
36
+ tmp_super_list[-1] = [word for word in tmp_super_list[-1] if word[pos] == letter]
37
+ counter = counter + 1
38
+ if len(tmp_super_list) != 0:
39
+ return [ i for i in tmp_super_list if len(i) > 0]
40
+ elif len(tmp) != 0 and len(tmp_super_list) == 0:
41
+ return [tmp]
42
+ else:
43
+ return [self.word_list]