import json
import requests
import random
import string
import secrets
import time
import re
import collections
try:
    from urllib.parse import parse_qs, urlencode, urlparse
except ImportError:
    from urlparse import parse_qs, urlparse
    from urllib import urlencode
add Codeadd Markdown
 
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
add Codeadd Markdown
 
vowels = ['a', 'e', 'i', 'o', 'u']
add Codeadd Markdown
 
# for ratio of vowels to length of word
def vowel_count(clean_word):
    count = 0
    for i in clean_word:
        if i in vowels:
            count = count+1.0
    return count/len(clean_word)
add Codeadd Markdown
 
f = open("/kaggle/input/hangmen/words_250000_train.txt", "r")
df = []
for x in f:
  df.append(x)
add Codeadd Markdown
for i in range(len(df)):
    df[i] = df[i].replace("\n", "")
add Codeadd Markdown
 
l=[]
for words in df:
    l.append(vowel_count(words))
l = pd.Series(l)
l.describe()
count    227300.000000
mean          0.386889
std           0.095527
min           0.000000
25%           0.333333
50%           0.384615
75%           0.444444
max           1.000000
dtype: float64
add Codeadd Markdown
bins = np.arange(0.0, 1.0, 0.05)
plt.hist(x = l, bins = bins)
​
(array([1.2490e+03, 2.0000e+00, 6.8100e+02, 1.7410e+03, 6.7780e+03,
        3.2538e+04, 3.5853e+04, 3.6370e+04, 6.0189e+04, 1.2807e+04,
        2.8992e+04, 7.8220e+03, 7.7600e+02, 1.1180e+03, 1.0800e+02,
        1.8300e+02, 5.4000e+01, 1.0000e+00, 0.0000e+00]),
 array([0.  , 0.05, 0.1 , 0.15, 0.2 , 0.25, 0.3 , 0.35, 0.4 , 0.45, 0.5 ,
        0.55, 0.6 , 0.65, 0.7 , 0.75, 0.8 , 0.85, 0.9 , 0.95]),
 <BarContainer object of 19 artists>)

add Codeadd Markdown
 
max_length = 0
for words in df:
    if(len(words)>max_length):
        max_length = len(words)
add Codeadd Markdown
 
n_word_dictionary = {i:[] for i in range(3, 30)}
count = 3
while count<=max_length:
    for words in df:
        if(len(words)>=count):
            for i in range(len(words)-count+1):
                #if words[i:i+count-1] not in n_word_dictionary[count]:
                n_word_dictionary[count].append(words[i:i+count]) 
    count = count+1
add Codeadd Markdown
# function to find number of times a letter come in whole dictionary, keeping count of letter 1 if it comes in a word else 0
def func(new_dictionary):
    dictx = collections.Counter()
    for words in new_dictionary:
        temp = collections.Counter(words)
        for i in temp:
            temp[i] = 1
            dictx = dictx + temp
    return dictx
add Codeadd Markdown
 
# function to generate a list of words which are substring in the original dictionary and of same length as clean word
def func2(n_word_dictionary, clean_word):
    new_dictionary = []
    l = len(clean_word)
    for dict_word in n_word_dictionary[l]:
        if re.match(clean_word,dict_word):
            new_dictionary.append(dict_word)
    return new_dictionary
add Codeadd Markdown
arrow_upwardarrow_downwarddelete
# HANGMAN_URL = "https://www.trexsim.com/trexsim/hangman"

class HangmanAPI(object):
    def __init__(self, access_token=None, session=None, timeout=None):
        self.hangman_url = self.determine_hangman_url()
        self.access_token = access_token
        self.session = session or requests.Session()
        self.timeout = timeout
        self.guessed_letters = []
        
        full_dictionary_location = "words_250000_train.txt"
        self.full_dictionary = self.build_dictionary(full_dictionary_location)
        self.full_dictionary_common_letter_sorted = collections.Counter("".join(self.full_dictionary)).most_common()
        
        self.current_dictionary = []
        
        # RL variables
        self.q_table = {}
        self.learning_rate = 0.1
        self.discount_factor = 0.9
        self.epsilon = 1.0
        self.epsilon_decay = 0.995
        self.min_epsilon = 0.01
        
    @staticmethod
    def determine_hangman_url():
        links = ['https://trexsim.com', 'https://sg.trexsim.com']
        data = {link: 0 for link in links}
        
        for link in links:
            requests.get(link)
            for i in range(10):
                s = time.time()
                requests.get(link)
                data[link] = time.time() - s
                
        link = sorted(data.items(), key=lambda x: x[1])[0][0]
        link += '/trexsim/hangman'
        return link
    
    def build_state(self, word, guessed_letters, tries_left):
        """Create a hashable state from the current word, guessed letters, and tries left."""
        clean_word = word[::2]  # Remove spaces
        state = (clean_word, "".join(sorted(guessed_letters)), tries_left)
        return state
    
    def update_q_table(self, state, action, reward, next_state):
        """Update Q-Table using Q-Learning formula."""
        if state not in self.q_table:
            self.q_table[state] = {letter: 0 for letter in 'abcdefghijklmnopqrstuvwxyz'}
        
        if next_state not in self.q_table:
            self.q_table[next_state] = {letter: 0 for letter in 'abcdefghijklmnopqrstuvwxyz'}
        
        q_current = self.q_table[state][action]
        q_next_max = max(self.q_table[next_state].values())
        
        # Q-Learning update rule
        self.q_table[state][action] = q_current + self.learning_rate * (reward + self.discount_factor * q_next_max - q_current)
    
    def guess(self, word, tries_left):
        """Guess the next letter based on the RL algorithm."""
        # Build the current state
        state = self.build_state(word, self.guessed_letters, tries_left)
        
        # Epsilon-greedy action selection
        if random.uniform(0, 1) < self.epsilon:
            # Explore: Random action
            available_actions = [letter for letter in 'abcdefghijklmnopqrstuvwxyz' if letter not in self.guessed_letters]
            guess_letter = random.choice(available_actions)
        else:
            # Exploit: Choose best action based on Q-Table
            if state not in self.q_table:
                self.q_table[state] = {letter: 0 for letter in 'abcdefghijklmnopqrstuvwxyz'}
            
            sorted_actions = sorted(self.q_table[state].items(), key=lambda x: x[1], reverse=True)
            guess_letter = next((letter for letter, _ in sorted_actions if letter not in self.guessed_letters), random.choice('abcdefghijklmnopqrstuvwxyz'))
        
        return guess_letter
    
    def reward(self, correct_guess):
        """Assign a reward based on the result of the guess."""
        if correct_guess:
            return 10  # Reward for correct guess
        else:
            return -5  # Penalty for incorrect guess

    def start_game(self, practice=True, verbose=True):
        """Play a full game of hangman, implementing the RL-based guessing."""
        # Reset guessed letters and dictionary
        self.guessed_letters = []
        self.current_dictionary = self.full_dictionary
        
        # Start new game
        response = self.request("/new_game", {"practice": practice})
        if response.get('status') == "approved":
            game_id = response.get('game_id')
            word = response.get('word')
            tries_remains = response.get('tries_remains')
            
            if verbose:
                print(f"New game started. Game ID: {game_id}. Tries left: {tries_remains}. Word: {word}")
            
            while tries_remains > 0:
                # Guess based on RL algorithm
                guess_letter = self.guess(word, tries_remains)
                self.guessed_letters.append(guess_letter)
                
                if verbose:
                    print(f"Guessing letter: {guess_letter}")
                
                # Make the guess and get response
                res = self.request("/guess_letter", {"request": "guess_letter", "game_id": game_id, "letter": guess_letter})
                
                if verbose:
                    print(f"Server response: {res}")
                
                status = res.get('status')
                tries_remains = res.get('tries_remains')
                correct_guess = res.get('correct_guess', False)
                
                # Assign reward and update Q-Table
                reward = self.reward(correct_guess)
                new_word = res.get('word')
                next_state = self.build_state(new_word, self.guessed_letters, tries_remains)
                self.update_q_table(state, guess_letter, reward, next_state)
                
                # Update epsilon (decay for exploration-exploitation trade-off)
                self.epsilon = max(self.min_epsilon, self.epsilon * self.epsilon_decay)
                
                if status == "success":
                    if verbose:
                        print("Game won!")
                    return True
                elif status == "failed":
                    if verbose:
                        print("Game lost.")
                    return False
                elif status == "ongoing":
                    word = res.get('word')
        else:
            if verbose:
                print("Failed to start a new game.")
        return False

# HANGMAN_URL = "https://www.trexsim.com/trexsim/hangman"
​
class HangmanAPI(object):
    def __init__(self, access_token=None, session=None, timeout=None):
        self.hangman_url = self.determine_hangman_url()
        self.access_token = access_token
        self.session = session or requests.Session()
        self.timeout = timeout
        self.guessed_letters = []
        
        full_dictionary_location = "words_250000_train.txt"
        self.full_dictionary = self.build_dictionary(full_dictionary_location)
        self.full_dictionary_common_letter_sorted = collections.Counter("".join(self.full_dictionary)).most_common()
        
        self.current_dictionary = []
        
        # RL variables
        self.q_table = {}
        self.learning_rate = 0.1
        self.discount_factor = 0.9
        self.epsilon = 1.0
        self.epsilon_decay = 0.995
        self.min_epsilon = 0.01
        
    @staticmethod
    def determine_hangman_url():
        links = ['https://trexsim.com', 'https://sg.trexsim.com']
        data = {link: 0 for link in links}
        
        for link in links:
            requests.get(link)
            for i in range(10):
                s = time.time()
                requests.get(link)
                data[link] = time.time() - s
                
        link = sorted(data.items(), key=lambda x: x[1])[0][0]
        link += '/trexsim/hangman'
        return link
    
    def build_state(self, word, guessed_letters, tries_left):
        """Create a hashable state from the current word, guessed letters, and tries left."""
        clean_word = word[::2]  # Remove spaces
        state = (clean_word, "".join(sorted(guessed_letters)), tries_left)
        return state
    
    def update_q_table(self, state, action, reward, next_state):
        """Update Q-Table using Q-Learning formula."""
        if state not in self.q_table:
            self.q_table[state] = {letter: 0 for letter in 'abcdefghijklmnopqrstuvwxyz'}
        
        if next_state not in self.q_table:
            self.q_table[next_state] = {letter: 0 for letter in 'abcdefghijklmnopqrstuvwxyz'}
        
        q_current = self.q_table[state][action]
        q_next_max = max(self.q_table[next_state].values())
        
        # Q-Learning update rule
        self.q_table[state][action] = q_current + self.learning_rate * (reward + self.discount_factor * q_next_max - q_current)
    
    def guess(self, word, tries_left):
        """Guess the next letter based on the RL algorithm."""
        # Build the current state
        state = self.build_state(word, self.guessed_letters, tries_left)
        
        # Epsilon-greedy action selection
        if random.uniform(0, 1) < self.epsilon:
            # Explore: Random action
            available_actions = [letter for letter in 'abcdefghijklmnopqrstuvwxyz' if letter not in self.guessed_letters]
            guess_letter = random.choice(available_actions)
        else:
            # Exploit: Choose best action based on Q-Table
            if state not in self.q_table:
                self.q_table[state] = {letter: 0 for letter in 'abcdefghijklmnopqrstuvwxyz'}
            
            sorted_actions = sorted(self.q_table[state].items(), key=lambda x: x[1], reverse=True)
            guess_letter = next((letter for letter, _ in sorted_actions if letter not in self.guessed_letters), random.choice('abcdefghijklmnopqrstuvwxyz'))
        
        return guess_letter
    
    def reward(self, correct_guess):
        """Assign a reward based on the result of the guess."""
        if correct_guess:
            return 10  # Reward for correct guess
        else:
            return -5  # Penalty for incorrect guess
​
    def start_game(self, practice=True, verbose=True):
        """Play a full game of hangman, implementing the RL-based guessing."""
        # Reset guessed letters and dictionary
        self.guessed_letters = []
        self.current_dictionary = self.full_dictionary
        
        # Start new game
        response = self.request("/new_game", {"practice": practice})
        if response.get('status') == "approved":
            game_id = response.get('game_id')
            word = response.get('word')
            tries_remains = response.get('tries_remains')
            
            if verbose:
                print(f"New game started. Game ID: {game_id}. Tries left: {tries_remains}. Word: {word}")
            
            while tries_remains > 0:
                # Guess based on RL algorithm
                guess_letter = self.guess(word, tries_remains)
                self.guessed_letters.append(guess_letter)
                
                if verbose:
                    print(f"Guessing letter: {guess_letter}")
                
                # Make the guess and get response
                res = self.request("/guess_letter", {"request": "guess_letter", "game_id": game_id, "letter": guess_letter})
                
                if verbose:
                    print(f"Server response: {res}")
                
                status = res.get('status')
                tries_remains = res.get('tries_remains')
                correct_guess = res.get('correct_guess', False)
                
                # Assign reward and update Q-Table
                reward = self.reward(correct_guess)
                new_word = res.get('word')
                next_state = self.build_state(new_word, self.guessed_letters, tries_remains)
                self.update_q_table(state, guess_letter, reward, next_state)
                
                # Update epsilon (decay for exploration-exploitation trade-off)
                self.epsilon = max(self.min_epsilon, self.epsilon * self.epsilon_decay)
                
                if status == "success":
                    if verbose:
                        print("Game won!")
                    return True
                elif status == "failed":
                    if verbose:
                        print("Game lost.")
                    return False
                elif status == "ongoing":
                    word = res.get('word')
        else:
            if verbose:
                print("Failed to start a new game.")
        return False
​
add Codeadd Markdown
api = HangmanAPI(access_token="775976eaf5c7653d7f9cc3f826ad3e", timeout=2000)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[29], line 1
----> 1 api = HangmanAPI(access_token="775976eaf5c7653d7f9cc3f826ad3e", timeout=2000)

Cell In[28], line 12, in HangmanAPI.__init__(self, access_token, session, timeout)
      9 self.guessed_letters = []
     11 full_dictionary_location = "words_250000_train.txt"
---> 12 self.full_dictionary = self.build_dictionary(full_dictionary_location)
     13 self.full_dictionary_common_letter_sorted = collections.Counter("".join(self.full_dictionary)).most_common()
     15 self.current_dictionary = []

AttributeError: 'HangmanAPI' object has no attribute 'build_dictionary'
add Codeadd Markdown
api.start_game(practice=1,verbose=True)
[total_practice_runs,total_recorded_runs,total_recorded_successes,total_practice_successes] = api.my_status() # Get my game stats: (# of tries, # of wins)
practice_success_rate = total_practice_successes / total_practice_runs
print('run %d practice games out of an allotted 100,000. practice success rate so f
correct whole code and make perfect hangmen project