python номер появления слова
Частотный анализ русского текста и облако слов на Python
Частотный анализ является одним из сравнительно простых методов обработки текста на естественном языке (NLP). Его результатом является список слов, наиболее часто встречающихся в тексте. Частотный анализ также позволяет получить представление о тематике и основных понятиях текста. Визуализировать его результаты удобно в виде «облака слов». Эта диаграмма содержит слова, размер шрифта которых отражает их популярность в тексте.
Обработку текста на естественном языке удобно производить с помощью Python, поскольку он является достаточно высокоуровневым инструментом программирования, имеет развитую инфраструктуру, хорошо зарекомендовал себя в сфере анализа данных и машинного обучения. Сообществом разработано несколько библиотек и фреймворков для решения задач NLP на Python. Мы в своей работе будем использовать интерактивный веб-инструмент для разработки python-скриптов Jupyter Notebook, библиотеку NLTK для анализа текста и библиотеку wordcloud для построения облака слов.
В сети представлено достаточно большое количество материала по теме анализа текста, но во многих статьях (в том числе русскоязычных) предлагается анализировать текст на английском языке. Анализ русского текста имеет некоторую специфику применения инструментария NLP. В качестве примера рассмотрим частотный анализ текста повести «Метель» А. С. Пушкина.
Проведение частотного анализа можно условно разделить на несколько этапов:
Загрузка данных
Открываем файл с помощью встроенной функции open, указываем режим чтения и кодировку. Читаем всё содержимое файла, в результате получаем строку text:
Длину текста – количество символов – можно получить стандартной функцией len:
Строка в python может быть представлена как список символов, поэтому для работы со строками также возможны операции доступа по индексам и получения срезов. Например, для просмотра первых 300 символов текста достаточно выполнить команду:
Предварительная обработка (препроцессинг) текста
Для проведения частотного анализа и определения тематики текста рекомендуется выполнить очистку текста от знаков пунктуации, лишних пробельных символов и цифр. Сделать это можно различными способами – с помощью встроенных функций работы со строками, с помощью регулярных выражений, с помощью операций обработки списков или другим способом.
Для начала переведём символы в единый регистр, например, нижний:
Используем стандартный набор символов пунктуации из модуля string:
string.punctuation представляет собой строку. Набор специальных символов, которые будут удалены из текста может быть расширен. Необходимо проанализировать исходный текст и выявить символы, которые следует удалить. Добавим к знакам пунктуации символы переноса строки, табуляции и другие символы, которые встречаются в нашем исходном тексте (например, символ с кодом \xa0):
Для удаления символов используем поэлементную обработку строки – разделим исходную строку text на символы, оставим только символы, не входящие в набор spec_chars и снова объединим список символов в строку:
Можно объявить простую функцию, которая удаляет указанный набор символов из исходного текста:
Её можно использовать как для удаления спец.символов, так и для удаления цифр из исходного текста:
Токенизация текста
Для последующей обработки очищенный текст необходимо разбить на составные части – токены. В анализе текста на естественном языке применяется разбиение на символы, слова и предложения. Процесс разбиения называется токенизация. Для нашей задачи частотного анализа необходимо разбить текст на слова. Для этого можно использовать готовый метод библиотеки NLTK:
Переменная text_tokens представляет собой список слов (токенов). Для вычисления количества слов в предобработанном тексте можно получить длину списка токенов:
Для вывода первых 10 слов воспользуемся операцией среза:
Для применения инструментов частотного анализа библиотеки NLTK необходимо список токенов преобразовать к классу Text, который входит в эту библиотеку:
Выведем тип переменной text:
К переменной этого типа также применимы операции среза. Например, это действие выведет 10 первых токенов из текста:
Подсчёт статистики встречаемости слов в тексте
Для подсчёта статистики распределения частот слов в тексте применяется класс FreqDist (frequency distributions):
Попытка вывести переменную fdist отобразит словарь, содержащий токены и их частоты – количество раз, которые эти слова встречаются в тексте:
Также можно воспользоваться методом most_common для получения списка кортежей с наиболее часто встречающимися токенами:
Частота распределения слов тексте может быть визуализирована с помощью графика. Класс FreqDist содержит встроенный метод plot для построения такого графика. Необходимо указать количество токенов, частоты которых будут показаны на графике. С параметром cumulative=False график иллюстрирует закон Ципфа: если все слова достаточно длинного текста упорядочить по убыванию частоты их использования, то частота n-го слова в таком списке окажется приблизительно обратно пропорциональной его порядковому номеру n.
Можно заметить, что в данный момент наибольшие частоты имеют союзы, предлоги и другие служебные части речи, не несущие смысловой нагрузки, а только выражающие семантико-синтаксические отношения между словами. Для того, чтобы результаты частотного анализа отражали тематику текста, необходимо удалить эти слова из текста.
Удаление стоп-слов
К стоп-словам (или шумовым словам), как правило, относят предлоги, союзы, междометия, частицы и другие части речи, которые часто встречаются в тексте, являются служебными и не несут смысловой нагрузки – являются избыточными.
Библиотека NLTK содержит готовые списки стоп-слов для различных языков. Получим список сто-слов для русского языка:
Следует отметить, что стоп-слова являются контекстно зависимыми – для текстов различной тематики стоп-слова могут отличаться. Как и в случае со спец.символами, необходимо проанализировать исходный текст и выявить стоп-слова, которые не вошли в типовой набор.
Список стоп-слов может быть расширен с помощью стандартного метода extend:
После удаления стоп-слов частота распределения токенов в тексте выглядит следующим образом:
Как видно, результаты частотного анализа стали более информативными и точнее стали отражать основную тематику текста. Однако, мы видим в результатах такие токены, как «владимир» и «владимира», которые являются, по сути, одним словом, но в разных формах. Для исправления этой ситуации необходимо слова исходного текста привести к их основам или изначальной форме – провести стемминг или лемматизацию.
Визуализация популярности слов в виде облака
В завершение нашей работы визуализируем результаты частотного анализа текста в виде «облака слов».
Для этого нам потребуются библиотеки wordcloud и matplotlib:
Для построения облака слов на вход методу необходимо передать строку. Для преобразования списка токенов после предобработки и удаления стоп-слов воспользуемся методом join, указав в качестве разделителя пробел:
Выполним вызов метода построения облака:
В результате получаем такое «облако слов» для нашего текста:
Глядя на него, можно получить общее представление о тематике и главных персонажах произведения.
Классификация текста с помощью Python и Scikit-Learn
Вступление
В этой статье мы рассмотрим реальный пример классификации текста. Мы будем обучать модель машинного обучения, способную предсказать, является ли данный обзор фильма положительным или отрицательным. Это классический пример сентиментального анализа, когда чувства людей по отношению к тому или иному субъекту классифицируются по различным категориям.
Набор данных
Распакуйте или извлеките набор данных после его загрузки. Откройте папку “txt_send token”. Папка содержит две подпапки: “neg” и “pos”. Если вы откроете эти папки, то увидите текстовые документы, содержащие обзоры фильмов.
Анализ настроений с помощью Scikit-Learn
Теперь, когда мы загрузили данные, пришло время увидеть некоторые действия. В этом разделе мы выполним ряд шагов, необходимых для прогнозирования настроений на основе отзывов о различных фильмах. Эти шаги можно использовать для любой задачи классификации текста. Мы будем использовать библиотеку Scikit-Learn Python для машинного обучения для обучения модели классификации текста.
Ниже приведены шаги, необходимые для создания модели классификации текста в Python:
Импорт библиотек
Выполните следующий сценарий для импорта необходимых библиотек:
Импорт набора данных
Мы будем использовать функцию load_files из библиотеки sklearn_datasets для импорта набора данных в наше приложение. Функция load_files автоматически делит набор данных на наборы данных и целевые наборы. Например, в нашем случае мы передадим ему путь к каталогу “text_send token”. Файл load_files будет рассматривать каждую папку внутри папки “text_send token” как одну категорию, и всем документам внутри этой папки будет присвоена соответствующая категория.
Выполните следующий скрипт, чтобы увидеть load_files функцию в действии:
Предварительная обработка текста
После импорта набора данных следующим шагом является предварительная обработка текста. Текст может содержать цифры, специальные символы и ненужные пробелы. В зависимости от проблемы, с которой мы сталкиваемся, нам может понадобиться или не понадобиться удалять эти специальные символы и цифры из текста. Однако ради объяснения мы удалим все специальные символы, цифры и ненужные пробелы из нашего текста. Выполните следующий сценарий для предварительной обработки данных:
В приведенном выше сценарии мы используем регулярные выражения из библиотеки Python re для выполнения различных задач предварительной обработки. Мы начинаем с удаления всех несловесных символов, таких как специальные символы, цифры и т. Д.
Далее мы удаляем все одиночные символы. Например, когда мы убираем знак препинания из “Давида” и заменяем его пробелом, мы получаем “Давида” и один символ “s”, который не имеет никакого значения. Для удаления таких одиночных символов мы используем \s+[a-zA-Z]\s+ регулярное выражение, которое заменяет все одиночные символы, имеющие пробелы с обеих сторон, одним пробелом.
Затем мы используем регулярное выражение \^[a-zA-Z]\s+ для замены одного символа из начала документа одним пробелом. Замена отдельных символов одним пробелом может привести к появлению нескольких пробелов, что не является идеальным решением.
Мы снова используем регулярное выражение \s+ для замены одного или нескольких пробелов одним пробелом. Когда у вас есть набор данных в байтовом формате, буква алфавита “b” добавляется перед каждой строкой. Регулярное выражение ^b\s+ удаляет “b” из начала строки. Следующий шаг-преобразовать данные в нижний регистр, чтобы слова, которые на самом деле одинаковы, но имеют разные падежи, можно было рассматривать одинаково.
Преобразование текста в числа
Машины, в отличие от людей, не могут понять сырой текст. Машины могут видеть только цифры. В частности, статистические методы, такие как машинное обучение, могут работать только с числами. Поэтому нам нужно преобразовать наш текст в числа.
Существуют различные подходы к преобразованию текста в соответствующую числовую форму. Модель мешка слов и Модель встраивания слов являются двумя наиболее часто используемыми подходами. В этой статье мы будем использовать модель мешка слов для преобразования нашего текста в числа.
Мешок слов
Следующий сценарий использует модель bag of words для преобразования текстовых документов в соответствующие числовые объекты:
Функция fit_transform класса CountVectorizer преобразует текстовые документы в соответствующие числовые объекты.
Поиск TFIDF
Подход “мешок слов” отлично подходит для преобразования текста в числа. Однако у него есть один недостаток. Он присваивает оценку слову на основе его появления в конкретном документе. При этом не учитывается тот факт, что это слово может также иметь высокую частоту встречаемости и в других документах. TFIDF решает эту проблему путем умножения частоты термина слова на обратную частоту документа. TF расшифровывается как “Частота термина”, а IDF-как “Обратная частота документа”.
Термин частота вычисляется как:
А обратная частота документа вычисляется как:
Значение TFIDF для слова в конкретном документе выше, если частота встречаемости этого слова выше в этом конкретном документе, но ниже во всех других документах.
Чтобы преобразовать значения, полученные с помощью модели bag of words, в значения TF IDF, выполните следующий скрипт:
Примечание:
Вы также можете напрямую конвертировать текстовые документы в значения функций TFIDF (без предварительного преобразования документов в функции bag of words), используя следующий скрипт:
Наборы для обучения и тестирования
Приведенный выше сценарий делит данные на 20% тестового набора и 80% обучающего набора.
Обучающая Модель Классификации текста и прогнозирования настроений
Мы разделили наши данные на обучающий и тестовый набор. Сейчас самое время увидеть реальное действие. Мы будем использовать алгоритм Случайного леса для обучения нашей модели. Вы можете использовать любую другую модель по вашему выбору.
Поздравляю, вы успешно обучили свою первую модель классификации текста и сделали некоторые прогнозы. Теперь самое время посмотреть на производительность модели, которую вы только что создали.
Оценка модели
Вывод выглядит следующим образом:
Сохранение и загрузка модели
В приведенном выше сценарии выполнение нашей модели машинного обучения не заняло много времени. Одной из причин быстрого времени обучения является тот факт, что у нас был относительно меньший тренировочный набор. У нас было 2000 документов, из которых 80% (1600) мы использовали для обучения. Однако в реальных сценариях могут быть миллионы документов. В таких случаях обучение алгоритмов может занять часы или даже дни (если у вас более медленные машины). Поэтому рекомендуется сохранить модель после ее обучения.
Мы можем сохранить нашу модель как объект pickle в Python. Для этого выполните следующий сценарий:
После выполнения описанного выше скрипта вы можете увидеть файл text_classifier в своем рабочем каталоге. Мы сохранили нашу обученную модель и можем использовать ее позже для прямого предсказания, без обучения.
Для загрузки модели мы можем использовать следующий код:
Вывод выглядит следующим образом:
Результат похож на тот, который мы получили ранее, который показал, что мы успешно сохранили и загрузили модель.
Вывод
Классификация текста-одна из наиболее часто используемых задач НЛП. В этой статье мы видели простой пример того, как классификация текста может быть выполнена в Python. Мы провели сентиментальный анализ рецензий на фильмы.
Регулярные выражения в Python от простого к сложному. Подробности, примеры, картинки, упражнения
Решил я давеча моим школьникам дать задачек на регулярные выражения для изучения. А к задачкам нужна какая-нибудь теория. И стал я искать хорошие тексты на русском. Пяток сносных нашёл, но всё не то. Что-то смято, что-то упущено. У этих текстов был не только фатальный недостаток. Мало картинок, мало примеров. И почти нет разумных задач. Ну неужели поиск IP-адреса — это самая частая задача для регулярных выражений? Вот и я думаю, что нет.
Про разницу (. ) / (. ) фиг найдёшь, а без этого знания в некоторых случаях можно только страдать.
Плюс в питоне есть немало регулярных плюшек. Например, re.split может добавлять тот кусок текста, по которому был разрез, в список частей. А в re.sub можно вместо шаблона для замены передать функцию. Это — реальные вещи, которые прямо очень нужны, но никто про это не пишет.
Так и родился этот достаточно многобуквенный материал с подробностями, тонкостями, картинками и задачами.
Надеюсь, вам удастся из него извлечь что-нибудь новое и полезное, даже если вы уже в ладах с регулярками.
PS. Решения задач школьники сдают в тестирующую систему, поэтому задачи оформлены в несколько формальном виде.
Содержание
Регулярное выражение — это строка, задающая шаблон поиска подстрок в тексте. Одному шаблону может соответствовать много разных строчек. Термин «Регулярные выражения» является переводом английского словосочетания «Regular expressions». Перевод не очень точно отражает смысл, правильнее было бы «шаблонные выражения». Регулярное выражение, или коротко «регулярка», состоит из обычных символов и специальных командных последовательностей. Например, \d задаёт любую цифру, а \d+ — задает любую последовательность из одной или более цифр. Работа с регулярками реализована во всех современных языках программирования. Однако существует несколько «диалектов», поэтому функционал регулярных выражений может различаться от языка к языку. В некоторых языках программирования регулярками пользоваться очень удобно (например, в питоне), в некоторых — не слишком (например, в C++).
Примеры регулярных выражений
Сила и ответственность
Регулярные выражения, или коротко, регулярки — это очень мощный инструмент. Но использовать их следует с умом и осторожностью, и только там, где они действительно приносят пользу, а не вред. Во-первых, плохо написанные регулярные выражения работают медленно. Во-вторых, их зачастую очень сложно читать, особенно если регулярка написана не лично тобой пять минут назад. В-третьих, очень часто даже небольшое изменение задачи (того, что требуется найти) приводит к значительному изменению выражения. Поэтому про регулярки часто говорят, что это write only code (код, который только пишут с нуля, но не читают и не правят). А также шутят: Некоторые люди, когда сталкиваются с проблемой, думают «Я знаю, я решу её с помощью регулярных выражений.» Теперь у них две проблемы. Вот пример write-only регулярки (для проверки валидности e-mail адреса (не надо так делать. )):
А вот здесь более точная регулярка для проверки корректности email адреса стандарту RFC822. Если вдруг будете проверять email, то не делайте так!Если адрес вводит пользователь, то пусть вводит почти что угодно, лишь бы там была собака. Надёжнее всего отправить туда письмо и убедиться, что пользователь может его получить.
Документация и ссылки
Основы синтаксиса
Шаблоны, соответствующие одному символу
Квантификаторы (указание количества повторений)
Жадность в регулярках и границы найденного шаблона
В тех случаях, когда это важно, условие на границу шаблона нужно обязательно добавлять в регулярку. О том, как это можно делать, будет дальше.
Пересечение подстрок
В обычной ситуации регулярки позволяют найти только непересекающиеся шаблоны. Вместе с проблемой границы слова это делает их использование в некоторых случаях более сложным. Например, если мы решим искать e-mail адреса при помощи неправильной регулярки \w+@\w+ (или даже лучше, [\w’._+-]+@[\w’._+-]+ ), то в неудачном случае найдём вот что:
Эксперименты в песочнице
Регулярки в питоне
Пример использования всех основных функций
Тонкости экранирования в питоне ( ‘\\\\\\\\foo’ )
Использование дополнительных флагов в питоне
Написание и тестирование регулярных выражений
Для написания и тестирования регулярных выражений удобно использовать сервис https://regex101.com (не забудьте поставить галочку Python в разделе FLAVOR слева) или текстовый редактор Sublime text 3.
Задачи — 1
В России применяются регистрационные знаки нескольких видов.
Общего в них то, что они состоят из цифр и букв. Причём используются только 12 букв кириллицы, имеющие графические аналоги в латинском алфавите — А, В, Е, К, М, Н, О, Р, С, Т, У и Х.
У частных легковых автомобилях номера — это буква, три цифры, две буквы, затем две или три цифры с кодом региона. У такси — две буквы, три цифры, затем две или три цифры с кодом региона. Есть также и другие виды, но в этой задаче они не понадобятся.
Вам потребуется определить, является ли последовательность букв корректным номером указанных двух типов, и если является, то каким.
На вход даются строки, которые претендуют на то, чтобы быть номером. Определите тип номера. Буквы в номерах — заглавные русские. Маленькие и английские для простоты можно игнорировать.
Допустимый формат e-mail адреса регулируется стандартом RFC 5322.
Если говорить вкратце, то e-mail состоит из одного символа @ (at-символ или собака), текста до собаки (Local-part) и текста после собаки (Domain part). Вообще в адресе может быть всякий беспредел (вкратце можно прочитать о нём в википедии). Довольно странные штуки могут быть валидным адресом, например:
«very.(),:;<>[]\».VERY.\»very@\\ \»very\».unusual»@[IPv6:2001:db8::1]
«()<>[]:,;@\\\»!#$%&’-/=?^_`<>|
.a»@(comment)exa-mple
Но большинство почтовых сервисов такой ад и вакханалию не допускают. И мы тоже не будем 🙂
PS. Совсем не обязательно делать все проверки только регулярками. Регулярные выражения — это просто инструмент, который делает часть задач простыми. Не нужно делать их назад сложными 🙂
Скобочные группы (. ) и перечисления |
Перечисления (операция «ИЛИ»)
Скобочные группы (группировка плюс квантификаторы)
Скобки плюс перечисления
Ещё примеры
Задачи — 2
Владимир устроился на работу в одно очень важное место. И в первом же документе он ничего не понял,
там были сплошные ФГУП НИЦ ГИДГЕО, ФГОУ ЧШУ АПК и т.п. Тогда он решил собрать все аббревиатуры, чтобы потом найти их расшифровки на http://sokr.ru/. Помогите ему.
Будем считать аббревиатурой слова только лишь из заглавных букв (как минимум из двух). Если несколько таких слов разделены пробелами, то они
считаются одной аббревиатурой.
Match-объекты
Группирующие скобки (. )
Тонкости со скобками и нумерацией групп.
Внутри группирующих скобок могут быть и другие группирующие скобки. В этом случае их нумерация производится в соответствии с номером появления открывающей скобки с шаблоне.
Группы и re.findall
Группы и re.split
В некоторых ситуация эта возможность бывает чрезвычайно удобна! Например, достаточно из предыдущего примера убрать лишние группы, и польза сразу станет очевидна!
Использование групп при заменах
Замена с обработкой шаблона функцией в питоне
Ещё одна питоновская фича для регулярных выражений: в функции re.sub вместо текста для замены можно передать функцию, которая будет получать на вход match-объект и должна возвращать строку, на которую и будет произведена замена. Это позволяет не писать ад в шаблоне для замены, а использовать удобную функцию. Например, «зацензурим» все слова, начинающиеся на букву «Х»:
Ссылки на группы при поиске
Только пообещайте, что не будете парсить сложный xml и тем более html при помощи регулярок! Регулярные выражения для этого не подходят. Используйте другие инструменты. Каждый раз, когда неопытный программист парсит html регулярками, в мире умирает котёнок. Если кажется «Да здесь очень простой html, напишу регулярку», то сразу вспоминайте шутку про две проблемы. Не нужно пытаться парсить html регулярками, даже Пётр Митричев не сможет это сделать в общем случае 🙂 Использование регулярных выражений при парсинге html подобно залатыванию резиновой лодки шилом. Закон Мёрфи для парсинга html и xml при помощи регулярок гласит: парсинг html и xml регулярками иногда работает, но в точности до того момента, когда правильность результата будет очень важна.
Задачи — 3
Владимиру потребовалось срочно запутать финансовую документацию. Но так, чтобы это было обратимо.
Он не придумал ничего лучше, чем заменить каждое целое число (последовательность цифр) на его куб. Помогите ему.
Хайку — жанр традиционной японской лирической поэзии века, известный с XIV века.
Оригинальное японское хайку состоит из 17 слогов, составляющих один столбец иероглифов. Особыми разделительными словами — кирэдзи — текст хайку делится на части из 5, 7 и снова 5 слогов. При переводе хайку на западные языки традиционно вместо разделительного слова использую разрыв строки и, таким образом, хайку записываются как трёхстишия.
Для простоты будем считать, что слогов ровно столько же, сколько гласных, не задумываясь о тонкостях.
Ввод | Вывод |
---|---|
Вечер за окном. / Еще один день прожит. / Жизнь скоротечна. | Хайку! |
Просто текст | Не хайку. Должно быть 3 строки. |
Как вишня расцвела! / Она с коня согнала / И князя-гордеца. | Не хайку. В 1 строке слогов не 5, а 6. |
На голой ветке / Ворон сидит одиноко… / Осенний вечер! | Не хайку. В 2 строке слогов не 7, а 8. |
Тихо, тихо ползи, / Улитка, по склону Фудзи, / Вверх, до самых высот! | Не хайку. В 1 строке слогов не 5, а 6. |
Жизнь скоротечна… / Думает ли об этом / Маленький мальчик. | Хайку! |
Шаблоны, соответствующие не конкретному тексту, а позиции
Отдельные части регулярного выражения могут соответствовать не части текста, а позиции в этом тексте. То есть такому шаблону соответствует не подстрока, а некоторая позиция в тексте, как бы «между» буквами.
Простые шаблоны, соответствующие позиции
Сложные шаблоны, соответствующие позиции (lookaround и Co)
Следующие шаблоны применяются в основном в тех случаях, когда нужно уточнить, что должно идти непосредственно перед или после шаблона, но при этом
не включать найденное в match-объект.
На всякий случай ещё раз. Каждый их этих шаблонов проверяет лишь то, что идёт непосредственно перед позицией или непосредственно после позиции. Если пару таких шаблонов написать рядом, то проверки будут независимы (то есть будут соответствовать AND в каком-то смысле).
lookaround на примере королей и императоров Франции
Людовик(?=VI) — Людовик, за которым идёт VI
Прочие фичи
Конечно, здесь описано не всё, что умеют регулярные выражения, и даже не всё, что умеют регулярные выражения в питоне. За дальнейшим можно обращаться к этому разделу. Из полезного за кадром осталась компиляция регулярок для ускорения многократного использования одного шаблона, использование именных групп и разные хитрые трюки.
А уж какие извращения можно делать с регулярными выражениями в языке Perl — поручик Ржевский просто отдыхает 🙂
Задачи — 4
Владимир написал свой открытый проект, именуя переменные в стиле «ВерблюжийРегистр».
И только после того, как написал о нём статью, он узнал, что в питоне для имён переменных принято использовать подчёркивания для разделения слов (under_score). Нужно срочно всё исправить, пока его не «закидали тапками».
Задача могла бы оказаться достаточно сложной, но, к счастью, Владимир совсем не использовал строковых констант и классов.
Поэтому любая последовательность букв и цифр, внутри которой есть заглавные, — это имя переменной, которое нужно поправить.
Довольно распространённая ошибка ошибка — это повтор слова.
Вот в предыдущем предложении такая допущена. Необходимо исправить каждый такой повтор (слово, один или несколько пробельных символов, и снова то же слово).
Ввод | Вывод |
---|---|
Довольно распространённая ошибка ошибка — это лишний повтор повтор слова слова. Смешно, не не правда ли? Не нужно портить хор хоровод. | Довольно распространённая ошибка — это лишний повтор слова. Смешно, не правда ли? Не нужно портить хор хоровод. |
Для простоты будем считать словом любую последовательность букв, цифр и знаков _ (то есть символов \w ).
Дан текст. Необходимо найти в нём любой фрагмент, где сначала идёт слово «олень», затем не более 5 слов, и после этого идёт слово «заяц».
Большие целые числа удобно читать, когда цифры в них разделены на тройки запятыми.
Переформатируйте целые числа в тексте.
Для простоты будем считать, что:
Разделите текст на предложения так, чтобы каждое предложение занимало одну строку.
Пустых строк в выводе быть не должно. Любые наборы из полее одного пробельного символа замените на один пробел.
В предыдущей задаче мы немного схалтурили.
Однако к этому моменту задача должна стать посильной!