import sys import numpy as np from gensim.models import KeyedVectors import random TOLERANCE = 1e-4 # tolérance sur la similarité cosinus if len(sys.argv) < 3: print("Usage: python cemantle.py ") sys.exit(1) first_word = sys.argv[1].lower() first_score = float(sys.argv[2]) / 100 # Détection de la langue lang = sys.argv[3] if len(sys.argv) > 3 else "en" if lang == "fr": TOLERANCE = 1e-2 with open("french_words.txt") as f: valid_words = set(w.strip() for w in f) print("Mode français : dictionnaire français chargé.") model_path = "frWac_non_lem_no_postag_no_phrase_200_cbow_cut0.bin" print("Chargement du modèle français (frWac cut100)...") model = KeyedVectors.load_word2vec_format(model_path, binary=True) else: with open("english_words.txt") as f: valid_words = set(w.strip() for w in f) print("Mode anglais : dictionnaire anglais chargé.") model_path = "GoogleNews-vectors-negative300.bin.gz" print("Chargement du modèle anglais...") model = KeyedVectors.load_word2vec_format(model_path, binary=True) if first_word not in model: print(f"Mot inconnu du modèle: {first_word}") sys.exit(1) # Calculer la similarité cosinus entre deux vecteurs cos = lambda a, b: np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)) def is_valid_word(word): if lang == "fr": return word.islower() and all(c.isalpha() for c in word) and word in valid_words and 3 <= len(word) <= 15 else: return word.islower() and word.isalpha() and word in valid_words and 3 <= len(word) <= 15 # Filtrer les mots à la bonne distance du mot donné, et qui sont valides vec1 = model[first_word] words = [] for w in model.index_to_key: if w == first_word: continue if not is_valid_word(w): continue sim = cos(vec1, model[w]) if abs(sim - first_score) < TOLERANCE: words.append(w) print(f"{len(words)} mots à la distance {first_score*100:.2f} de '{first_word}' (valides)") while words: guess = random.choice(words) print(f"Try: {guess}") s = input("Score: ") if s == "n": words.remove(guess) print(f"Mot refusé, {len(words)} restants.") continue try: score = float(s) / 100 except ValueError: print("Entrée invalide, recommencez.") continue vec_guess = model[guess] # Filtrer les mots à la bonne distance du guess words = [w for w in words if abs(cos(vec_guess, model[w]) - score) < TOLERANCE] print(f"{len(words)} mots restants à la distance {score*100:.2f} de '{guess}'") if not words: print("Plus aucun mot possible. Terminé.") break if len(words) == 1: print(f"Plus qu'un seul mot possible: {words[0]}") break