Наивное деление слова по слогам

Мое внимание привлекла задача по разделению слова на слоги: дело в том, что это интуитивно просто, но сформулировать правило словами, думаю, никто не сможет. Да и из того, что кто-нибудь сформулирует, всегда легко найти дюжину исключений. Создание базы данных «валидных слогов» я решил отбросить в сторону и попробовал решить задачу, основываясь лишь на закономерностях в чередовании гласных с согласными, т.к. именно гласные в русском языке лежат в основе слогообразования. Представляю вашему вниманию то что у меня получилось.

Простые слова

Рассмотрим простое слово: МО-ЛО-КО. Три гласных, следовательно, три слога. Но нужно еще определить, какие согласные к каким слогам относятся. Интуитивно понятно, что согласные стоящие перед гласной относятся к ее слогу. Так и запишем: «слог  состоит из согласных, стоящих перед гласной, и самой гласной».

Следующий пример — слово ДРОЗД. Слог один, и очевидно что все согласные принадлежат ему. Так как в этом слове согласные стоит после гласной и, тем не менее, принадлежат ее слогу, можно расширить наше понятие слога, добавив к нему: «и нескольких согласных после гласной». Нескольких — это скольких? Как минимум, в случае, если это последний слог, то всех. А вот если не последний, то это хороший вопрос.

Разделяй и властвуй

Нужно разрешить эту «междоусобицу» между гласными за право владения согласными и я предлагаю разрешить его следующим образом:

«Если согласная одна, то она принадлежит той гласной, что справа от нее, если две- то каждая из них принадлежит ближайшей у ней гласной, а если же согласных три и больше (не уверен, что такие слова вообще есть), то к гласной слева принадлежит только первая, а остальные- к правой.»

Кроме того, малину портят знаки Ь и Ъ. Смотрим на слова ВЕСТЬ-Я и ЗА-ЗЕ-ВАТЬ-СЯ и дополняем  правило: если знак стоит в «спорной» области, на которую претендуют две гласных, то в таком случае именно знак определяет границу между слогами. Сам знак, разумеется, принадлежит тому-же слогу, что и согласная слева от него, т.к. лишь смягчает ее и не является отдельным звуком.

Бесспорно, такое тупое правило не может объять богатства великого и могучего со всеми его исключениями и исключениями из исключений. Именно поэтому я назвал его «наивным». Но у него есть свои плюсы: во-первых, оно очень простое- код можнопри желании уложить в твит, а во-вторых, позволяет правильно разделить на слоги 90% русских, да и вообще, славянских слов, вот примеры:

Съешь е-ще э-тих мяг-ких фран-цуз-ских бу-лок
Бу-ря мгло-ю не-бо кро-ет, вих-ри снеж-ны-е кру-тя
Бе-ла-я бе-ре-за под мо-им ок-ном

Есть, куда расти

Направлений для улучшений много. Например, очень похоже, что согласные тяготеют к Р сильнее чем к остальным. Поэтому, в случае трех согласных, центральная присоединяется к Р, даже если она стоит слева. С и Т тоже очень часто являются исключением в разделении, притягиваясь друг ко другу. Так же, большую проблему представляют приставки, заканчивающиеся на открытый слог (ПЕРЕ-, ВЫ-, ЗА- и т.д.) Не зная, какие приставки «бывают», а какие «не бывают» правильно отделить слоги, похоже, невозможно. Но нельзя сказать, что приставки делятся на слоги отдельно от корня, т.к. много приставок, которые являются частью слога корня. В общем, дальше можно усложнять алгоритм, но не уверен, что это решит все проблемы: все дело в самом русском языке — он не формализуемый на 100%, многое применяется так «просто потому что».

Код

Кому интересно продолжить — код выложен на GitHub

Если просто интересно, как я реализовал это, то коротко: сначала из слова строится маска согласных-гласных, по которой проходимся незамысловатым регексом:

#coding=utf-8
import re
vowels = set(u'аеёиоуыэюя')
sign_chars = set(u'ъь')
pattern_str = u"(c*[ьъ]?vc+[ьъ](?=v))|(c*[ьъ]?v(?=v|cv))|(c*[ьъ]?vc[ъь]?(?=cv|ccv))|(c*[ьъ]?v[cьъ]*(?=$))"
pattern = re.compile(pattern_str)

def get_syllables(word):
    mask = ''.join(['v' if c in vowels else c if c in sign_chars else 'c' for c in word.lower()])
    return [word[m.start():m.end()] for m in pattern.finditer(mask)]

word = raw_input(u'слово:').decode('utf-8')
print '-'.join(get_syllables(word))

Спасибо, что читаете!

Запись опубликована в рубрике Алгоритмы с метками , , . Добавьте в закладки постоянную ссылку.

5 комментариев: Наивное деление слова по слогам

  1. Макс говорит:

    Спасибо что пишете!

  2. Mike говорит:

    Слово «экспресс» неправильно разбирает: получается один слог «кспресс».
    Что там нужно подкрутить?

  3. Viktor говорит:

    Я когда-то думал над этой темой — и у меня следующий интуитивный алгоритм вышел: выделяются гласные и середина расстояния между ними — это граница слога. Тоже не 100%, кроме того, середина не всегда (50%) определяется однозначно — и тут уже можно ваш подход.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *