Поиграть


Фотографии знаменитостей, Герои нашего времени

Определение схожести русских слов

Автор: ЖЖ юзер http://nomen.livejournal.com/

Code (php)
  1.  
  2. <?php
  3. # to Arthur
  4.  
  5. // (cc) me, 23/08/2007-27/08/2007
  6.  
  7. $str = "к скалам бурым";
  8. print "ru_soundex($str) = ".ru_soundex($str)."
  9. \r\n";
  10.  
  11. $str = "с каламбуром";
  12. print "ru_soundex($str) = ".ru_soundex($str)."
  13. \r\n";;
  14.  
  15. function ru_soundex($source)
  16. {
  17. $res = ;
  18.  
  19. $literal = array();
  20. // ассоциативный массив букв
  21. // параметры звуков гласный / согласный
  22.  
  23. // для гласных переход буквы в звук(и), редуцированный/нет, предполагаемые правила ударения исходя из кол-ва слогов (stressed syllable)
  24. // реализована проверка предполагаемого ударения
  25.  
  26. // для согласных переход букв[ы] в звук(и), редуцируемый/нет, правила редуцирования
  27.  
  28. // vowel
  29. $literal[‘А’] = array(’status’=>‘гласный’,’sound’=>‘а’,’stressed’=>‘а’); // никогда не меняется
  30. $literal[‘Е’] = array(’status’=>‘гласный’,’sound’=>‘и’,’stressed’=>‘э’, ‘АаЕеЁёИиОоУуЭэЮюЯяЬьЫыЪъ’ => ‘йэ’); // - особые правила, для этой буквы, стоящей после указанных, а также в начале слов
  31. $literal[‘Ё’] = array(’status’=>‘гласный’,’sound’=>‘о’,’stressed’=>‘о’, ‘АаЕеЁёИиОоУуЭэЮюЯяЬьЫыЪъ’ => ‘йо’);
  32. $literal[‘И’] = array(’status’=>‘гласный’,’sound’=>‘и’,’stressed’=>‘и’);
  33. $literal[‘О’] = array(’status’=>‘гласный’,’sound’=>‘а’,’stressed’=>‘о’);
  34. $literal[‘У’] = array(’status’=>‘гласный’,’sound’=>‘у’,’stressed’=>‘у’);
  35. $literal[‘Ы’] = array(’status’=>‘гласный’,’sound’=>‘ы’,’stressed’=>‘ы’);
  36. $literal[‘Э’] = array(’status’=>‘гласный’,’sound’=>‘э’,’stressed’=>‘э’);
  37. $literal[‘Ю’] = array(’status’=>‘гласный’,’sound’=>‘у’,’stressed’=>‘у’, ‘АаЕеЁёИиОоУуЭэЮюЯяЬьЫыЪъ’ => ‘йу’);
  38. $literal[‘Я’] = array(’status’=>‘гласный’,’sound’=>‘а’,’stressed’=>‘а’, ‘АаЕеЁёИиОоУуЭэЮюЯяЬьЫыЪъ’ => ‘йа’); // заяц произносится как [зайец]
  39. $v_pattern = ‘АаЕеЁёИиОоУуЭэЮюЯяЬьЫыЪъ’;
  40.  
  41. // кстати, надо добавить выкусывание гласных из концов слов, заканчивающихся на согласный-гласный-звонкий согласный (-ром, -лем, итд) гласная очень часто сглатывается
  42. // зы: это здесь не реализовано %)
  43. // проверено: soundex и сам с этим неплохо справляется
  44.  
  45. // звонкие согласные редуцируются при удвоении.
  46. // звонкие согласные переходят в парный глухой перед глухим
  47. // глухие редуцируются полностью перед глухими.
  48.  
  49. // consonant
  50. // в отличие от гласных, для согласных условие "стоит перед указанной или в конце слова"
  51. $literal[‘Б’] = array(’status’=>‘согласный’,’sound’=>‘б’, ‘КкПпСсТтФфХхЦцЧчШшЩщ’ => ‘п’);
  52. $literal[‘В’] = array(’status’=>‘согласный’,’sound’=>‘в’, ‘КкПпСсТтФфХхЦцЧчШшЩщ’ => ‘ф’);
  53. $literal[‘Г’] = array(’status’=>‘согласный’,’sound’=>‘Г’, ‘КкПпСсТтФфХхЦцЧчШшЩщ’ => ‘к’);
  54. $literal[‘Д’] = array(’status’=>‘согласный’,’sound’=>‘д’, ‘КкПпСсТтФфХхЦцЧчШшЩщ’ => ‘т’);
  55. $literal[‘Ж’] = array(’status’=>‘согласный’,’sound’=>‘ж’, ‘КкПпСсТтФфХхЦцЧчШшЩщ’ => ‘ш’);
  56. $literal[‘З’] = array(’status’=>‘согласный’,’sound’=>‘з’, ‘КкПпСсТтФфХхЦцЧчШшЩщ’ => ‘с’);
  57. $literal[‘Й’] = array(’status’=>‘согласный’,’sound’=>‘й’);
  58. $literal[‘К’] = array(’status’=>‘согласный’,’sound’=>‘к’, ‘КкПпСсТтФфХхЦцЧчШшЩщ’ => );
  59. $literal[‘Л’] = array(’status’=>‘согласный’,’sound’=>‘л’);
  60. $literal[‘М’] = array(’status’=>‘согласный’,’sound’=>‘м’);
  61. $literal[‘Н’] = array(’status’=>‘согласный’,’sound’=>‘н’);
  62. $literal[‘П’] = array(’status’=>‘согласный’,’sound’=>‘п’, ‘КкПпСсТтФфХхЦцЧчШшЩщ’ => );
  63. $literal[‘Р’] = array(’status’=>‘согласный’,’sound’=>‘р’);
  64. $literal[‘С’] = array(’status’=>‘согласный’,’sound’=>‘с’); // а вот С не хочет редуцироваться, на первый взгляд…
  65. $literal[‘Т’] = array(’status’=>‘согласный’,’sound’=>‘т’, ‘КкПпСсТтФфХхЦцЧчШшЩщ’ => );
  66. $literal[‘Ф’] = array(’status’=>‘согласный’,’sound’=>‘ф’, ‘КкПпСсТтФфХхЦцЧчШшЩщ’ => ); // спорно
  67. $literal[‘Х’] = array(’status’=>‘согласный’,’sound’=>‘х’);
  68. $literal[‘Ц’] = array(’status’=>‘согласный’,’sound’=>‘ц’);
  69. $literal[‘Ч’] = array(’status’=>‘согласный’,’sound’=>‘чь’); // всегда мягкий
  70. $literal[‘Ш’] = array(’status’=>‘согласный’,’sound’=>‘ш’);
  71. $literal[‘Щ’] = array(’status’=>‘согласный’,’sound’=>‘щь’);
  72.  
  73. // спецсимволы
  74. $literal[‘Ъ’] = array(’status’=>‘знак’,’sound’=>‘ ‘); // только разделительный. делит жёстко
  75. $literal[‘Ь’] = array(’status’=>‘знак’,’sound’=>‘ь’); // даже если делит, то мягко
  76.  
  77. $literal[‘ТС’] = array(’status’=>‘сочетание’,’sound’=>‘ц’);
  78. $literal[‘ТЬС’] = $literal[‘ТС’];
  79. $literal[‘ШЬ’] = array(’status’=>‘сочетание’,’sound’=>‘ш’); // всегда твёрдый. и это не единстенный рудимент языка
  80.  
  81. $literal[‘СОЛНЦ’] = array(’status’=>‘сочетание’,’sound’=>‘сонц’);
  82. $literal[‘ЯИЧНИЦ’] = array(’status’=>‘сочетание’,’sound’=>‘еишниц’);
  83. $literal[‘КОНЕЧНО’] = array(’status’=>‘сочетание’,’sound’=>‘канешно’);
  84. $literal[‘ЧТО’] = array(’status’=>‘сочетание’,’sound’=>‘што’);
  85. $literal[‘ЗАЯ’] = array(’status’=>‘сочетание’,’sound’=>‘зайэ’); // да-да. не только [зайэц], но и [зайэвльэнийэ]
  86.  
  87.  
  88.  
  89.  
  90. $sound = str_to_upper($source);
  91.  
  92. // сначала сочетания
  93. foreach( array_filter($literal,
  94. create_function(‘$item’,‘if( $item["status"] === "сочетание") return true; return false;’))
  95. as $sign => $translate )
  96. $sound = str_replace($sign,$translate["sound"],$sound);
  97.  
  98. // потом знаки
  99. foreach( array_filter($literal,
  100. create_function(‘$item’,‘if( $item["status"] === "знак") return true; return false;’))
  101. as $sign => $voice )
  102. $sound = str_replace($sign,$translate["sound"],$sound);
  103.  
  104.  
  105. // разделяем на слова, определяем кол-во слогов, заменяем ударный/безударный гласный (единственный или предполагая второй в двух-трёхсложном слове, предпредпоследний - в остальных)
  106.  
  107. $words = preg_split(‘~[,.\~`1234567890-=\~!@#$%^&*()_+|{}\]\];:\’"<>/? ]~’, $sound, -1, PREG_SPLIT_NO_EMPTY);
  108.  
  109. // гласные
  110. foreach( array_filter($literal,
  111. create_function(‘$item’,‘if( $item["status"] === "гласный") return true; return false;’))
  112. as $sign => $translate )
  113. {
  114. // для каждого слова
  115. foreach( $words as &$word )
  116. {
  117. // кол-во гласных
  118. $vowel = preg_match_all("~[$v_pattern]~", $word, $del_me );
  119. // готовим
  120. $cur_pos = 0;
  121. $cur_vowel = 0;
  122. while( false !== $cur_pos = strpos($word,$sign,$cur_pos) )
  123. {
  124. $cur_vowel++;
  125. // print $cur_pos.’ = ‘.$sound[$cur_pos]."
  126. \r\n";
  127. if( sizeof($translate)==4 && ($cur_pos === 0 || strpos( $v_pattern , $word[$cur_pos-1] )))
  128. {
  129. $word = substr_replace($word,$translate[$v_pattern],$cur_pos,1);
  130. }
  131. elseif( 1 == $vowel )
  132. $word = substr_replace($word,$translate["stressed"],$cur_pos,1); //
  133. elseif( 2 == $vowel && 1 == $cur_vowel )
  134. $word = substr_replace($word,$translate["stressed"],$cur_pos,1); // предполагаем, что в двухсложных словах первый слог ударный
  135. elseif( 3 <= $vowel && $cur_vowel == $vowel - 2 )
  136. $word = substr_replace($word,$translate["stressed"],$cur_pos,1); // предполагаем, что слог ударный предпредпоследний
  137. else
  138. $word = substr_replace($word,$translate["sound"],$cur_pos,1);
  139. $cur_pos++;
  140. }
  141. }
  142. }
  143.  
  144. $sound = implode( $words, ‘ ‘ ); // клеим обратно
  145.  
  146. // согласные
  147. foreach( array_filter($literal,
  148. create_function(’$item’,'if( $item["status"] === "согласный") return true; return false;’))
  149. as $sign => $translate )
  150. {
  151. // готовим
  152. $cur_pos = 0;
  153. while( false !== $cur_pos = strpos($sound,$sign,$cur_pos) )
  154. {
  155. // print $cur_pos.’ = ‘.$sound[$cur_pos]."
  156. \r\n";
  157. if( sizeof($translate)==3 )
  158. {
  159. $x = array_pop(array_keys($translate)); // снимаем третий элемент
  160. if( strpos( $x, $sound[$cur_pos+1] ) || $cur_pos === strlen($sound) )
  161. {
  162. $sound = substr_replace($sound,$translate[$x],$cur_pos,1);
  163. } elseif ( $sound[$cur_pos] === $sound[$cur_pos+1] )
  164. $sound = substr_replace($sound,$translate["sound"],$cur_pos,2); // все двойные редуцируются
  165. else
  166. $sound = substr_replace($sound,$translate["sound"],$cur_pos,1);
  167.  
  168. } else
  169. {
  170. $sound = substr_replace($sound,$translate["sound"],$cur_pos,1);
  171. }
  172.  
  173. $cur_pos++;
  174. }
  175. }
  176. // алес. фонемы привели к одному виду
  177. // дальше используем любой алгоритм для вычисления числового эквивалента
  178.  
  179. // но остаётся сомнение. очень хочется расстаться с глухими предлогами перед глухими согласными ("к скалам")
  180.  
  181.  
  182. $sound = preg_replace(’~[,.\~`1234567890-=\~!@#$%^&*()_+|{}\]\];:\’"<>/? ]~‘,’‘,$sound) ;
  183.  
  184. // print $sound;
  185. // print str_to_translit($sound);
  186. // print soundex(str_to_translit($sound));
  187.  
  188. $res = str_to_upper($source[0]).substr(soundex(str_to_translit($sound)),1);
  189.  
  190. return $res;
  191. }
  192.  
  193.  
  194.  
  195. // (c) http://ru2.php.net/manual/en/function.strtoupper.php#74574
  196. //Russian
  197. function str_to_upper($str){
  198. return strtr($str,
  199. "abcdefghijklmnopqrstuvwxyz".
  200. "\xE0\xE1\xE2\xE3\xE4\xE5".
  201. "\xb8\xe6\xe7\xe8\xe9\xea".
  202. "\xeb\xeC\xeD\xeE\xeF\xf0".
  203. "\xf1\xf2\xf3\xf4\xf5\xf6".
  204. "\xf7\xf8\xf9\xfA\xfB\xfC".
  205. "\xfD\xfE\xfF",
  206. "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
  207. "\xC0\xC1\xC2\xC3\xC4\xC5".
  208. "\xA8\xC6\xC7\xC8\xC9\xCA".
  209. "\xCB\xCC\xCD\xCE\xCF\xD0".
  210. "\xD1\xD2\xD3\xD4\xD5\xD6".
  211. "\xD7\xD8\xD9\xDA\xDB\xDC".
  212. "\xDD\xDE\xDF");
  213. }
  214.  
  215. function str_to_translit($str){
  216. return strtr($str,
  217. "abcdefghijklmnopqrstuvwxyz".
  218. "\xE0\xE1\xE2\xE3\xE4\xE5".
  219. "\xb8\xe6\xe7\xe8\xe9\xea".
  220. "\xeb\xeC\xeD\xeE\xeF\xf0".
  221. "\xf1\xf2\xf3\xf4\xf5\xf6".
  222. "\xf7\xf8\xf9\xfA\xfB\xfC".
  223. "\xfD\xfE\xfF",
  224. "abcdefghijklmnopqrstuvwxyz".
  225. "abvgde".
  226. "?*ziik".
  227. "lmnopr".
  228. "stufhc".
  229. "4ww\”y`".
  230. "eua");
  231. }
  232. ?>
  233.  

+1+2+3+4+5 (2 голосов, в среднем: 5 из 5)
Загрузка... Загрузка...

Оставьте комментарий

Блог разработчика / заказать: siku игрушки
инвестирование в форекс
Купить нижнее белье в интернет-магазине Дикая Орхидея.
Есть отличный трос для веб-мастеров, и мыло