import random import re def filter_initial(letters, wordlist): regexp = re.compile(f"[{''.join(letters)}]+") return [w for w in wordlist if regexp.fullmatch(w)] def filter(new_letter, old_letters, wordlist): regexp = re.compile(f"[{''.join(old_letters)}]*{new_letter}[{new_letter}{''.join(old_letters)}]*") return [w for w in wordlist if regexp.fullmatch(w)] class WordLottery: """This word lottery makes it 20 x less probable to again draw a word that had already been drawn previously.""" def __init__(self, words): self.words = words.copy() self.sub = None def add(self, word): self.words.append(word) def lots(self): if self.sub: return len(self.words) + self.sub.lots() / 20 else: return len(self.words) def draw(self): lots = self.lots() r = random.random() if r * lots < len(self.words): draw_i = random.randrange(0, len(self.words)) result_word = self.words[draw_i] del self.words[draw_i:draw_i+1] if not self.sub: self.sub = WordLottery([result_word]) else: self.sub.add(result_word) return result_word else: if self.sub: return self.sub.draw() else: raise RuntimeError("This was not supposed to happen. r: {r}, lots: {lots}, self.words: {len(self.words}.") def write_words(filtered, outdir, outname, words_per_lesson, blanks): lottery = WordLottery(filtered) with open(f"{outdir}/{outname}", "w") as out: for _ in range(0, words_per_lesson): out.write(lottery.draw()) out.write(blanks) out.write("\n") def mk_lessons(wordlist, learn_order, outdir, words_per_lesson = 50, blanks=" "): for lesson_name in learn_order.keys(): if "new_letter" in learn_order[lesson_name]: old_letters = learn_order[lesson_name]['old_letters'] new_letter = learn_order[lesson_name]['new_letter'] filtered = filter(new_letter, old_letters, wordlist) else: letters = learn_order[lesson_name]['letters'] filtered = filter_initial(letters, wordlist) if "new_words" in learn_order[lesson_name]: if learn_order[lesson_name]["new_words"] != len(filtered): raise RuntimeError(f"Lesson {lesson_name}: Wrong word count should: {learn_order[lesson_name]['new_words']} is: {len(filtered)}.") for i in range(0, 10): write_words(filtered, outdir, f"{lesson_name}_{i}.txt", words_per_lesson, blanks)