<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0">

<channel>

<title>Блог об аналитике, визуализации данных, data science и BI, заметки с тегом: solver</title>
<link>http://test.leftjoin.ru/tags/solver/</link>
<description></description>
<generator>E2 (v3365; Aegea)</generator>

<item>
<title>Решение головоломок Wordle с помощью Basic Python</title>
<guid isPermaLink="false">129</guid>
<link>http://test.leftjoin.ru/all/how-to-solve-wordle/</link>
<comments>http://test.leftjoin.ru/all/how-to-solve-wordle/</comments>
<description>
&lt;p class="note"&gt;Перевод статьи &lt;a href="https://www.inspiredpython.com/article/solving-wordle-puzzles-with-basic-python"&gt;“Solving Wordle Puzzles with Basic Python”&lt;/a&gt; автора &lt;a href="https://www.inspiredpython.com/author/mickey-petersen"&gt;Mickey Petersen&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://test.leftjoin.ru/pictures/2022-01-24-18.26.50.jpg" border="0" width="100%" height="100%"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Вы наверняка слышали о Wordle? Это словесная головоломка не так проста, как кажется на первый взгляд. Вас просят угадать английское «слово дня», которое состоит из пяти букв. Если вы ошибетесь, вам дадут несколько подсказок: буква в слове будет &lt;i&gt;зеленой&lt;/i&gt;, если вы правильно угадали нужную букву в нужном месте; &lt;i&gt;желтой&lt;/i&gt;, если эта буква присутствует в слове, но не на этом месте; и серой, если буквы вообще нет в слове.&lt;/p&gt;
&lt;p&gt;На самом деле, решать эту головоломку довольно сложно! Вот как вы можете написать Wordle Solver на Python, с использованием множеств, представления списков (list comprehension) и капелькой удачи!&lt;/p&gt;
&lt;h2&gt;Суть головоломки&lt;/h2&gt;
&lt;p&gt;Каждый день Wordle генерирует новое слово, которое нужно угадать. Поскольку у нас есть только шесть попыток — сайт использует файлы cookie для отслеживания вашего прогресса — попытки нужно использовать аккуратно!&lt;/p&gt;
&lt;p&gt;На первый взгляд, есть несколько подсказок, которые упрощают решение:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Слово состоит ровно из пяти букв.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="2"&gt;
&lt;li&gt;Слово из английского языка и использовать можно только алфавит — никаких знаков препинания, цифр или других символов.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="3"&gt;
&lt;li&gt;Любая попытка дает подсказки:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Зеленая буква, если буква и её место в слове правильные.&lt;/li&gt;
&lt;li&gt;Желтая буква, если буква присутствует в слове, но было выбрано не то место.&lt;/li&gt;
&lt;li&gt;Серая буква, если буквы вообще нет в слове.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="4"&gt;
&lt;li&gt;Существует конечное число слов, и их количество дополнительно ограничено словарем, используемым Wordle.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Поскольку я не хочу пытаться извлечь тот же словарь, что использует Wordle (это слишком просто), вместо этого я буду использовать свободно доступный словарь, который устанавливается через Linux в директорию &lt;b&gt;/usr/share/dict/american-english&lt;/b&gt;. Словарь — это текстовый файл с одним словом в каждой строке.&lt;/p&gt;
&lt;h2&gt;Загрузка и генерация слов&lt;/h2&gt;
&lt;p&gt;Для начала нам понадобится словарь — вы можете установить любой удобный вам или использовать уже установленный, если такой есть.&lt;/p&gt;
&lt;p&gt;Далее нам нужно закодировать правила игры:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;import string

DICT = &amp;quot;/usr/share/dict/american-english&amp;quot;

ALLOWABLE_CHARACTERS = set(string.ascii_letters)
ALLOWED_ATTEMPTS = 6
WORD_LENGTH = 5&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;У нас есть всего шесть попыток; длина слова равна пяти, и мы можем использовать все доступные буквы английского алфавита.&lt;/p&gt;
&lt;p&gt;Я преобразовываю допустимые символы в Python set(), чтобы использовать функции, которые доступны для работы с множествами, для проверки наличия букв в слове — но об этом чуть позже.&lt;/p&gt;
&lt;p&gt;Теперь я могу сгенерировать множество тех слов, которые соответствуют правилам:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;from pathlib import Path

WORDS = {
  word.lower()
  for word in Path(DICT).read_text().splitlines()
  if len(word) == WORD_LENGTH and set(word) &amp;lt; ALLOWABLE_CHARACTERS
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Здесь я использую представление списков (list comprehension) для создания множества допустимых слов. Я использую отличный класс Path для чтения непосредственно из файла. Если вы еще не знакомы с Path, &lt;a href="https://www.inspiredpython.com/article/common-path-patterns"&gt;я рекомендую вам узнать о нем&lt;/a&gt;, поскольку это очень удобный инструмент.&lt;/p&gt;
&lt;p&gt;Так, я фильтрую слова из словаря, которые имеют правильную длину и в которых набор символов в слове является подмножеством ALLOWABLE_CHARACTERS. Другими словами, выбираются только слова, которые составлены из набора допустимых символов.&lt;/p&gt;
&lt;h2&gt;Алфавитно-частотный анализ на английского языка&lt;/h2&gt;
&lt;p&gt;Особенность английского языка заключается в неравномерном распределении букв, используемых в словах. Например, буква &lt;b&gt;E&lt;/b&gt; используется гораздо чаще, чем &lt;b&gt;X&lt;/b&gt;. Поэтому, если мы сможем генерировать слова с наиболее распространенными буквами, у нас больше шансов угадать некоторые или даже все буквы в слове. Таким образом, выигрышная стратегия состоит в том, чтобы придумать систему, которая вычислит наиболее популярные буквы английского языка.&lt;/p&gt;
&lt;p&gt;К счастью, у нас есть словарь английских слов!&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;from collections import Counter
from itertools import chain

LETTER_COUNTER = Counter(chain.from_iterable(WORDS))&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Класс &lt;i&gt;Counter&lt;/i&gt; — полезное изобретение! Это модифицированный словарь, который считает количество повторений каждого элемента. Когда вы передаете ему список элементов, они становятся ключами, а затем он сохраняет количество появлений каждого ключа в его значение. Это как раз то, что нам нужно, чтобы посчитать популярность каждой буквы среди всех английских слов из 5 букв.&lt;/p&gt;
&lt;p&gt;Для этого я использую малоизвестную функцию chain из модуля &lt;i&gt;itertools&lt;/i&gt;. Эта функция имеет один скрытый метод &lt;i&gt;from_iterable&lt;/i&gt;, который берет один элемент и итерирует его:&lt;/p&gt;
&lt;p&gt;Я думаю, что лучше всего объяснить на конкретном примере:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; list(chain.from_iterable([&amp;quot;inspired&amp;quot;, &amp;quot;python&amp;quot;]))
['i', 'n', 's', 'p', 'i', 'r', 'e', 'd', 'p', 'y', 't', 'h', 'o', 'n']&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Поскольку строки также можно итерировать, а &lt;i&gt;WORDS&lt;/i&gt; — это множество строк, то мы можем разбить это множество (или список и т. д.) на составные элементы. Это очень полезное свойство строк; вы можете прогнать строку через &lt;i&gt;set()&lt;/i&gt; и получить все уникальные символы строки:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; set(&amp;quot;hello&amp;quot;)
{'e', 'h', 'l', 'o'}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;i&gt;Множества созданы по образцу своих математических тезок.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Это означает, что множества могут содержать только уникальные значения — без дубликатов — и они неупорядочены. Вот почему порядок в множестве и в строке  получился разным.&lt;/p&gt;
&lt;p&gt;Множества обладают многими полезными функциями, такими как проверка, содержится ли одно множество полностью в другом множестве (подмножестве); получение элементов, содержащихся в обоих множествах (пересечение); совмещение элементов двух множеств (объединение) и так далее.&lt;/p&gt;
&lt;p&gt;Итак, мы посчитали количество букв во всем словаре, и вот что получилось:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; LETTER_COUNTER
Counter({'h': 828,
         'o': 1888,
         'n': 1484,
         'e': 3106,
         's': 2954,
         'v': 338,
         # ...etc...
        })&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Так, мы получили только абсолютное количество букв в словаре. Теперь нужно разделить его на общее количество букв, чтобы перейти к относительным величинам. К счастью, в классе Counter есть удобный метод total, который может посчитать общее количество букв всех слов словаря.&lt;/p&gt;
&lt;p&gt;Затем составляем таблицу частот:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;LETTER_FREQUENCY = {
    character: value / LETTER_COUNTER.total()
    for character, value in LETTER_COUNTER.items()
}&lt;/code&gt;&lt;/pre&gt;&lt;p class="note"&gt;Метод Counter.total() был добавлен в Python 3.10, поэтому, если вы используете более старую версию Python, вы можете заменить его на sum(LETTER_COUNTER.values()), который делает то же самое.&lt;/p&gt;
&lt;p&gt;Здесь я использую представление словарей (&lt;i&gt;dictionary comprehension&lt;/i&gt;) для обработки каждого ключа и значения LETTER_COUNTER (это модифицированный словарь) и деления каждого значения на общее количество символов:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; LETTER_FREQUENCY
{ 'h': 0,02804403048264183,
  'o': 0,06394580863674852,
  'n': 0,050262489415749366,
  'e': 0,10519898391193903,
  's': 0.10005080440304827,
  # ...etc...
  }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;И теперь у нас есть идеальный счетчик букв в подмножестве словаря, которые мы считаем существующими словами Wordle. Обратите внимание, что я не делал эти операции для всего словаря — я обработал только те части, которые нам интересны. Маловероятно, что это сильно повлияло бы на ранжирование популярности букв, но в конечном итоге мы руководствуемся именно этим набором слов.&lt;/p&gt;
&lt;p&gt;Теперь нам нужен способ оценки каждого слова, чтобы мы могли предположить, какие слова встретятся с наибольшей вероятностью. Итак, нам нужно взять нашу таблицу частоты и создать функцию подсчета популярности слов, которая оценивает, насколько «популярны» буквы в этом слове:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;def calculate_word_commonality(word):
    score = 0.0
    for char in word:
        score += LETTER_FREQUENCY[char]
    return score / (WORD_LENGTH - len(set(word)) + 1)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Снова вспоминаем, что строка является итерируемой, и перебираем каждую букву в слове. Затем получаем популярность каждой буквы и суммируем их. Потом общее количество делится на длину слова минус количество уникальных символов (плюс один, чтобы предотвратить деление на ноль).&lt;/p&gt;
&lt;p&gt;Это не то что бы удивительная функция оценки слов, но она проста и взвешивает слова таким образом, что более уникальным символам придается больший вес. В идеале нам нужно как можно больше уникальных, часто встречающихся символов, чтобы максимизировать вероятность получения зеленых или желтых совпадений в Wordle.&lt;/p&gt;
&lt;p&gt;Быстрый тест подтверждает, что слова с редкими и повторяющимися символами имеют более низкий вес, чем слова с частыми и более уникальными символами.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; calculate_word_commonality(&amp;quot;fuzzy&amp;quot;)
0.04604572396274344&lt;/code&gt;&lt;/pre&gt;&lt;pre class="e2-text-code"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; calculate_word_commonality(&amp;quot;arose&amp;quot;)
0.42692633361558&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Все, что нам сейчас нужно — придумать способ сортировки и отображения этих слов, чтобы игрок мог выбирать из них:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;import operator

def sort_by_word_commonality(words):
    sort_by = operator.itemgetter(1)
    return sorted(
        [(word, calculate_word_commonality(word)) for word in words],
        key=sort_by,
        reverse=True,
    )

def display_word_table(word_commonalities):
    for (word, freq) in word_commonalities:
        print(f&amp;quot;{word:&amp;lt;10} | {freq:&amp;lt;5.2}&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;С помощью sort_by_word_commonality я создаю отсортированный (от большего к меньшему) список кортежей, где каждый кортеж содержит слово и рассчитанный балл для этого слова. Ключ, по которому я сортирую, — это относительная популярность слова в словаре.&lt;/p&gt;
&lt;p&gt;Я не использую лямбду для получения первого элемента; для таких простых вещей я предпочитаю operator.itemgetter, который делает то же самое.&lt;/p&gt;
&lt;p&gt;Также, я добавил функцию быстрого отображения для форматирования слов и их оценки в простую таблицу.&lt;/p&gt;
&lt;p&gt;Теперь поговорим о самом решении головоломки.&lt;/p&gt;
&lt;h2&gt;Решение головоломки Wordle&lt;/h2&gt;
&lt;p&gt;Поскольку я создаю его как простое консольное приложение, я собираюсь использовать input() и print().&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;def input_word():
    while True:
        word = input(&amp;quot;Input the word you entered&amp;gt; &amp;quot;)
        if len(word) == WORD_LENGTH and word.lower() in WORDS:
            break
    return word.lower()


def input_response():
    print(&amp;quot;Type the color-coded reply from Wordle:&amp;quot;)
    print(&amp;quot;  G for Green&amp;quot;)
    print(&amp;quot;  Y for Yellow&amp;quot;)
    print(&amp;quot;  ? for Gray&amp;quot;)
    while True:
        response = input(&amp;quot;Response from Wordle&amp;gt; &amp;quot;)
        if len(response) == WORD_LENGTH and set(response) &amp;lt;= {&amp;quot;G&amp;quot;, &amp;quot;Y&amp;quot;, &amp;quot;?&amp;quot;}:
            break
        else:
            print(f&amp;quot;Error - invalid answer {response}&amp;quot;)
    return response&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Функционал приложения очень прост. Нужно узнать у пользователя слово WORD_LENGTH, которое он ввел в игре Wordle, и записать ответ от Wordle. Поскольку есть только три возможных цвета для буквы (зеленый, желтый и серый), ответ закодирован в простую строку из трех символов: G, Y и ?.&lt;/p&gt;
&lt;p&gt;Я также добавил обработку ошибок на тот случай, если пользователь ошибается при вводе данных, повторяя цикл до тех пор, пока не будет задана правильная последовательность. Я делаю это, снова преобразовывая полученную информацию в множество, а затем проверяя, является ли это множество подмножеством допустимых ответов.&lt;/p&gt;
&lt;h2&gt;Фильтрация зеленых, желтых и серых букв с помощью вектора слова&lt;/h2&gt;
&lt;p&gt;Зеленая буква указывает на правильность буквы и ее места в слове. Желтый означает, что место неправильное, но буква в слове присутствует; а серый что буквы нигде нет.&lt;/p&gt;
&lt;p&gt;Другой способ интерпретации этой информации заключается в том, что пока Wordle не сообщит нам, какие буквы зеленые, желтые или серые, существуют все варианты.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;word_vector = [set(string.ascii_lowercase) for _ in range(WORD_LENGTH)]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Я создаю список из пяти множеств, так как нам нужно определить 5 букв слова. Каждый элемент списка — это множество всех строчных английских букв. Проходясь по каждому множеству, я могу удалять буквы, в соответствии с тем, как окрашены буквы после попытки:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Зеленая буква дает нам информацию только по текущему множеству&lt;br /&gt;
Это означает, что если я встречу зеленую букву на втором месте, то я могу изменить второе множество и оставить только эту букву.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Желтые буквы исключают возможность использовать эту букву на этом месте&lt;br /&gt;
Таким образом, все буквы, кроме этой, технически могут оказаться на этом месте. Удаление буквы из набора в этой позиции гарантирует, что мы не сможем выбрать слова, в которых эта буква стоит на этом месте.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Серые буквы подразумевают исключение буквы из всего вектора.&lt;br /&gt;
Следовательно, эта буква должна быть удалена из всех множеств в векторе слова.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Теперь нам нужна функция, которая выбирает слова, которые соответствуют текущему вектору слова. Есть несколько способов сделать это, но я предлагаю вот такой красивый и простой вариант:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;def match_word_vector(word, word_vector):
    assert len(word) == len(word_vector)
    for letter, v_letter in zip(word, word_vector):
        if letter not in v_letter:
            return False
    return True&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Этот подход использует метод &lt;b&gt;zip&lt;/b&gt; для попарного сопоставления каждого символа в слове и каждого символа в векторе слова.&lt;/p&gt;
&lt;p&gt;Проходимся по каждому множеству, и, если буквы на определенном месте нет в соответствующем множестве, то цикл прерывается и слово исключается. Если все в порядке и цикл отрабатывает до последней буквы, то мы получаем ответ True и выходим из цикла, отмечая совпадение слова с вектором.&lt;/p&gt;
&lt;h2&gt;Проверяем слова на соответствие&lt;/h2&gt;
&lt;p&gt;Принимая во внимание все правила игры, теперь можем написать функцию поиска, которая фильтрует список слов с учетом ответов, которые мы получили от Wordle.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;def match(word_vector, possible_words):
    return [word for word in possible_words if match_word_vector(word, word_vector)]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Эта функция объединяет в себе все правила, которые мы обсудили выше, и ищет с помощью представления списков (list comprehension). Каждое слово проверяется на соответствие с word_vector с помощью match_word_vector.&lt;/p&gt;
&lt;h2&gt;Сортировка результатов&lt;/h2&gt;
&lt;p&gt;Наконец, нам нужно создать небольшой UI, который может многократно запрашивать нужный нам ответ.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;def solve():
    possible_words = WORDS.copy()
    word_vector = [set(string.ascii_lowercase) for _ in range(WORD_LENGTH)]
    for attempt in range(1, ALLOWED_ATTEMPTS + 1):
        print(f&amp;quot;Attempt {attempt} with {len(possible_words)} possible words&amp;quot;)
        display_word_table(sort_by_word_commonality(possible_words)[:15])
        word = input_word()
        response = input_response()
        for idx, letter in enumerate(response):
            if letter == &amp;quot;G&amp;quot;:
                word_vector[idx] = {word[idx]}
            elif letter == &amp;quot;Y&amp;quot;:
                try:
                    word_vector[idx].remove(word[idx])
                except KeyError:
                    pass
            elif letter == &amp;quot;?&amp;quot;:
                for vector in word_vector:
                    try:
                        vector.remove(word[idx])
                    except KeyError:
                        pass
        possible_words = match(word_vector, possible_words)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Функция solve() включает в себя некоторые элементы, которые мы уже обсудили. Затем попадаем в цикл от 1 до ALLOWED_ATTEMPTS + 1, и после каждой попытки мы отображаем номер текущей попытки и количество оставшихся возможных слов. Затем мы вызываем функцию display_word_table, которая выводит красивую таблицу из 15 совпадений с наибольшим рейтингом популярности слова. Затем функции нужно узнать слово, которое пользователь в итоге ввел и ответ Wordle.&lt;/p&gt;
&lt;p&gt;После этого мы проходимся по ответу Wordle, отмечая какой букве соответствует ответ (последовательность цветов). Код прост: мы сопоставляем каждый из трех возможных цветов с соответствующим контейнером (зеленый — с word_vector и т. д.) и применяем правила, которые мы обсудили выше.&lt;/p&gt;
&lt;p&gt;Наконец, мы заново берем possible_words и проверяем совпадение с новым вектором слова с помощью match, сокращая множество потенциальных вариантов.&lt;/p&gt;
&lt;h2&gt;Давайте проверим, как это работает&lt;/h2&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="http://test.leftjoin.ru/pictures/wordle.png" width="518" height="476" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Все начинается с запуска функции solve() (для краткости часть вывода опущена):&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; Attempt 1 with 5905 possible words
arose      | 0.43
raise      | 0.42

   ... etc ...

Input the word you entered&amp;gt; arose
Type the color-coded reply from Wordle:
  G for Green
  Y for Yellow
  ? for Gray
Response from Wordle&amp;gt; ?Y??Y
Attempt 2 with 829 possible words
liter      | 0.34
liner      | 0.34

   ... etc ...

Input the word you entered&amp;gt; liter
Response from Wordle&amp;gt; ???YY
Attempt 3 with 108 possible words
nerdy      | 0.29
nehru      | 0.28

   ... etc ...

Input the word you entered&amp;gt; nerdy
Response from Wordle&amp;gt; ?YY?G
Attempt 4 with 25 possible words
query      | 0.24
chewy      | 0.21

   ... etc ...

Input the word you entered&amp;gt; query
Response from Wordle&amp;gt; GGGGG
Attempt 5 with 1 possible words
query      | 0.24&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Резюме&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Представления (Comprehensions) — мощный инструмент Python&lt;br /&gt;
Они могут совмещать итерацию с фильтрацией, но если вы злоупотребите этой функцией, добавляя слишком много циклов for или слишком много условных операторов, код может стать нечитаемым. Избегайте сильной вложенности этих операторов, если это возможно.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Множества — полезный тип объекта в Python&lt;br /&gt;
Множества их их верное использование делают код более стабильным, более математически правильным и более кратким. Главное — знать, когда и как их использовать. В нашем решении множества сыграли существенную роль — не пренебрегайте ими!&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Регулярные выражения могут помочь описать все требования к поиску&lt;br /&gt;
Хотя это не было использовано в коде, совпадение (или несовпадение) шаблона и слова — это то, что регулярные выражения делают круче всего. Подумайте, как можно переписать мэтчинг и векторизацию слов с помощью регулярных выражений.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Модули itertools и collections содержат очень полезные инструменты&lt;br /&gt;
Вы можете многого добиться с базовым знанием Python, если знаете, как именно можно использовать встроенные модули. Модуль itertools особенно полезен, если вы вам нужно провернуть итеративные вычисления.&lt;/li&gt;
&lt;/ul&gt;
</description>
<pubDate>Wed, 26 Jan 2022 15:18:49 +0300</pubDate>
</item>


</channel>
</rss>