Определение схожести русских слов
Автор: ЖЖ юзер http://nomen.livejournal.com/
Code (php)
-
-
<?php
-
# to Arthur
-
-
// (cc) me, 23/08/2007-27/08/2007
-
-
$str = "к скалам бурым";
-
\r\n";
-
-
$str = "с каламбуром";
-
\r\n";;
-
-
function ru_soundex($source)
-
{
-
$res = ”;
-
-
// ассоциативный массив букв
-
// параметры звуков гласный / согласный
-
-
// для гласных переход буквы в звук(и), редуцированный/нет, предполагаемые правила ударения исходя из кол-ва слогов (stressed syllable)
-
// реализована проверка предполагаемого ударения
-
-
// для согласных переход букв[ы] в звук(и), редуцируемый/нет, правила редуцирования
-
-
// vowel
-
$literal[‘Е’] = array(’status’=>‘гласный’,’sound’=>‘и’,’stressed’=>‘э’, ‘АаЕеЁёИиОоУуЭэЮюЯяЬьЫыЪъ’ => ‘йэ’); // - особые правила, для этой буквы, стоящей после указанных, а также в начале слов
-
$literal[‘Ё’] = array(’status’=>‘гласный’,’sound’=>‘о’,’stressed’=>‘о’, ‘АаЕеЁёИиОоУуЭэЮюЯяЬьЫыЪъ’ => ‘йо’);
-
$literal[‘Ю’] = array(’status’=>‘гласный’,’sound’=>‘у’,’stressed’=>‘у’, ‘АаЕеЁёИиОоУуЭэЮюЯяЬьЫыЪъ’ => ‘йу’);
-
$literal[‘Я’] = array(’status’=>‘гласный’,’sound’=>‘а’,’stressed’=>‘а’, ‘АаЕеЁёИиОоУуЭэЮюЯяЬьЫыЪъ’ => ‘йа’); // заяц произносится как [зайец]
-
$v_pattern = ‘АаЕеЁёИиОоУуЭэЮюЯяЬьЫыЪъ’;
-
-
// кстати, надо добавить выкусывание гласных из концов слов, заканчивающихся на согласный-гласный-звонкий согласный (-ром, -лем, итд) гласная очень часто сглатывается
-
// зы: это здесь не реализовано %)
-
// проверено: soundex и сам с этим неплохо справляется
-
-
// звонкие согласные редуцируются при удвоении.
-
// звонкие согласные переходят в парный глухой перед глухим
-
// глухие редуцируются полностью перед глухими.
-
-
// consonant
-
// в отличие от гласных, для согласных условие "стоит перед указанной или в конце слова"
-
$literal[‘С’] = array(’status’=>‘согласный’,’sound’=>‘с’); // а вот С не хочет редуцироваться, на первый взгляд…
-
-
// спецсимволы
-
-
$literal[‘ТЬС’] = $literal[‘ТС’];
-
$literal[‘ШЬ’] = array(’status’=>‘сочетание’,’sound’=>‘ш’); // всегда твёрдый. и это не единстенный рудимент языка
-
-
$literal[‘ЗАЯ’] = array(’status’=>‘сочетание’,’sound’=>‘зайэ’); // да-да. не только [зайэц], но и [зайэвльэнийэ]
-
-
-
-
-
$sound = str_to_upper($source);
-
-
// сначала сочетания
-
as $sign => $translate )
-
-
// потом знаки
-
as $sign => $voice )
-
-
-
// разделяем на слова, определяем кол-во слогов, заменяем ударный/безударный гласный (единственный или предполагая второй в двух-трёхсложном слове, предпредпоследний - в остальных)
-
-
$words = preg_split(‘~[,.\~`1234567890-=\~!@#$%^&*()_+|{}\]\];:\’"<>/? ]~’, $sound, -1, PREG_SPLIT_NO_EMPTY);
-
-
// гласные
-
as $sign => $translate )
-
{
-
// для каждого слова
-
foreach( $words as &$word )
-
{
-
// кол-во гласных
-
// готовим
-
$cur_pos = 0;
-
$cur_vowel = 0;
-
{
-
$cur_vowel++;
-
// print $cur_pos.’ = ‘.$sound[$cur_pos]."
-
\r\n";
-
if( sizeof($translate)==4 && ($cur_pos === 0 || strpos( $v_pattern , $word[$cur_pos-1] )))
-
{
-
$word = substr_replace($word,$translate[$v_pattern],$cur_pos,1);
-
}
-
elseif( 1 == $vowel )
-
$word = substr_replace($word,$translate["stressed"],$cur_pos,1); //
-
elseif( 2 == $vowel && 1 == $cur_vowel )
-
$word = substr_replace($word,$translate["stressed"],$cur_pos,1); // предполагаем, что в двухсложных словах первый слог ударный
-
elseif( 3 <= $vowel && $cur_vowel == $vowel - 2 )
-
$word = substr_replace($word,$translate["stressed"],$cur_pos,1); // предполагаем, что слог ударный предпредпоследний
-
else
-
$word = substr_replace($word,$translate["sound"],$cur_pos,1);
-
$cur_pos++;
-
}
-
}
-
}
-
-
$sound = implode( $words, ‘ ‘ ); // клеим обратно
-
-
// согласные
-
foreach( array_filter($literal,
-
create_function(’$item’,'if( $item["status"] === "согласный") return true; return false;’))
-
as $sign => $translate )
-
{
-
// готовим
-
$cur_pos = 0;
-
while( false !== $cur_pos = strpos($sound,$sign,$cur_pos) )
-
{
-
// print $cur_pos.’ = ‘.$sound[$cur_pos]."
-
\r\n";
-
if( sizeof($translate)==3 )
-
{
-
$x = array_pop(array_keys($translate)); // снимаем третий элемент
-
if( strpos( $x, $sound[$cur_pos+1] ) || $cur_pos === strlen($sound) )
-
{
-
$sound = substr_replace($sound,$translate[$x],$cur_pos,1);
-
} elseif ( $sound[$cur_pos] === $sound[$cur_pos+1] )
-
$sound = substr_replace($sound,$translate["sound"],$cur_pos,2); // все двойные редуцируются
-
else
-
$sound = substr_replace($sound,$translate["sound"],$cur_pos,1);
-
-
} else
-
{
-
$sound = substr_replace($sound,$translate["sound"],$cur_pos,1);
-
}
-
-
$cur_pos++;
-
}
-
}
-
// алес. фонемы привели к одному виду
-
// дальше используем любой алгоритм для вычисления числового эквивалента
-
-
// но остаётся сомнение. очень хочется расстаться с глухими предлогами перед глухими согласными ("к скалам")
-
-
-
$sound = preg_replace(’~[,.\~`1234567890-=\~!@#$%^&*()_+|{}\]\];:\’"<>/? ]~‘,’‘,$sound) ;
-
-
// print $sound;
-
// print str_to_translit($sound);
-
// print soundex(str_to_translit($sound));
-
-
$res = str_to_upper($source[0]).substr(soundex(str_to_translit($sound)),1);
-
-
return $res;
-
}
-
-
-
-
// (c) http://ru2.php.net/manual/en/function.strtoupper.php#74574
-
//Russian
-
function str_to_upper($str){
-
return strtr($str,
-
"abcdefghijklmnopqrstuvwxyz".
-
"\xE0\xE1\xE2\xE3\xE4\xE5".
-
"\xb8\xe6\xe7\xe8\xe9\xea".
-
"\xeb\xeC\xeD\xeE\xeF\xf0".
-
"\xf1\xf2\xf3\xf4\xf5\xf6".
-
"\xf7\xf8\xf9\xfA\xfB\xfC".
-
"\xfD\xfE\xfF",
-
"ABCDEFGHIJKLMNOPQRSTUVWXYZ".
-
"\xC0\xC1\xC2\xC3\xC4\xC5".
-
"\xA8\xC6\xC7\xC8\xC9\xCA".
-
"\xCB\xCC\xCD\xCE\xCF\xD0".
-
"\xD1\xD2\xD3\xD4\xD5\xD6".
-
"\xD7\xD8\xD9\xDA\xDB\xDC".
-
"\xDD\xDE\xDF");
-
}
-
-
function str_to_translit($str){
-
return strtr($str,
-
"abcdefghijklmnopqrstuvwxyz".
-
"\xE0\xE1\xE2\xE3\xE4\xE5".
-
"\xb8\xe6\xe7\xe8\xe9\xea".
-
"\xeb\xeC\xeD\xeE\xeF\xf0".
-
"\xf1\xf2\xf3\xf4\xf5\xf6".
-
"\xf7\xf8\xf9\xfA\xfB\xfC".
-
"\xfD\xfE\xfF",
-
"abcdefghijklmnopqrstuvwxyz".
-
"abvgde".
-
"?*ziik".
-
"lmnopr".
-
"stufhc".
-
"4ww\”y`".
-
"eua");
-
}
-
?>
-
-
