Skip to content

Instantly share code, notes, and snippets.

@ddv88

ddv88/php Secret

Created August 20, 2018 10:36
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ddv88/8b8d9377d37eaf3e306dee716b79a082 to your computer and use it in GitHub Desktop.
Save ddv88/8b8d9377d37eaf3e306dee716b79a082 to your computer and use it in GitHub Desktop.
Russian cities declension
public static function declension(string $word) {
//Согласные
$consonants = ["б", "в", "г", "д", "ж", "з", "й", "к", "л", "м", "н", "п", "р", "с", "т", "ф", "х", "ц", "ч", "ш", "щ", "ь"];
//Гласные
$vocal = ["а", "у", "о", "ы", "и", "э", "я", "ю", "ё", "е"];
//Глухие согласные
$deafConsonants = ["п", "ф", "к", "т", "ш", "с", "х", "ц", "ч", "щ"];
//Звонкие согласные
$voicedConsonants = ["б", "в", "г", "д", "ж", "з", "л", "м", "н", "р"];
//Общие окончания
$endings = [
"ий","ай","ая","ты","ей","ри","ды","ое","ец","ый","ны","ие","ые","бо","но","во","ть","ро","ор","ма","ау","ко","кт","ну","ян","ар","нь","ый","лы","ль",
"чи","ки","ой","ок","аы","ни"
];
//Окончание при глухой согласной
$deafEndings = ["ий" => "ом", "ой" => "ом"];
//Окончание при звонкой согласной
$voicedEndings = ["ий" => "ем", "ой" => "ое", "ец" => "це"];
//Простые окончания
$regularEndings = [
"ай" => "ае","ая" => "ой","ты" => "тах","ей" => "ее","ри" => "рях","ды" => "дах","лы" => "лах","ое" => "ом","ор" => "ору","ец" => "це","ый" => "ом",
"ны" => "нах","ие" => "их","ые" => "ых","ий" => "ом","ль" => "ле","нь" => "не","чи" => "чах","ки" => "ках","ок" => "ке","аы" => "ау","ни" => "нях"
];
//Окончание при третьем гласном знаке
$vocalEndings = ["ень" => "не", "оби" => "би", "лец" => "льце", "очи" => "очи"];
//Несклоняемые окончания
$noDeclension = ["ну", "бо", "но", "во", "ть", "ро", "ма", "ау", "ко", "кт", "ян", "ар", "ак", "ев", "ас", "ид", "он", "ыл", "сь"];
//Проверяем сложное название или простое по наличию дефиса или пробела
preg_match("~(-на-|-|\s)~", $word, $delimiter) ? $word = explode($delimiter[0], $word) : null;
//Если сложно выполняем склонение для каждой части отдельно
if (is_array($word)) {
foreach ($word as $key => $value) {
//Получаем последний знак
$singleChar = mb_substr($value, -1);
//Определяем гласная или согласная
if (in_array($singleChar, $vocal)) {//Если гласная
//Получаем окончание из 2 знаков
$twoChars = mb_strtolower(mb_substr($value, -2));
if (!in_array($twoChars, $noDeclension)) {
if (in_array($twoChars, $endings)) {
//Если окончание присутствует в массиве получаем третий знак
$thirdChar = mb_strtolower(mb_substr($value, -3, 1));
//Если глухой
if (in_array($thirdChar, $deafConsonants)) {
if (array_key_exists($twoChars, $deafEndings)) {
$word[$key] = mb_substr($value, 0, -2) . $deafEndings[$twoChars];
} else {
$word[$key] = mb_substr($value, 0, -2) . $regularEndings[$twoChars];
}
//Если звонкий
} elseif (in_array($thirdChar, $voicedConsonants)) {
if (array_key_exists($twoChars, $voicedEndings)) {
$word[$key] = mb_substr($value, 0, -2) . $voicedEndings[$twoChars];
} else {
$word[$key] = mb_substr($value, 0, -2) . $regularEndings[$twoChars];
}
//Если третий символ гласный
} elseif (in_array($thirdChar, $vocal)) {
//Получаем окончание из 3 знаков
$threeChars = mb_substr($value, -3);
if (array_key_exists($threeChars, $vocalEndings)) {
$word[$key] = mb_substr($value, 0, -3) . $vocalEndings[$threeChars];
} else {
$word[$key] = mb_substr($value, 0, -2) . $regularEndings[$twoChars];
}
//Или берем стандартное окнчание
} else {
$word[$key] = mb_substr($value, 0, -2) . $regularEndings[$twoChars];
}
} else {
$word[$key] = mb_substr($value, 0, -1) . "е";
}
}
}
if (in_array($singleChar, $consonants)) {//Если согласная
//Получаем окончание из 2 знаков
$twoChars = mb_strtolower(mb_substr($value, -2));
if (!in_array($twoChars, $noDeclension)) {
if (in_array($twoChars, $endings)) {
//Если окончание присутствует в массиве получаем третий знак
$thirdChar = mb_strtolower(mb_substr($value, -3, 1));
if (in_array($thirdChar, $deafConsonants)) {
if (array_key_exists($twoChars, $deafEndings)) {
$word[$key] = mb_substr($value, 0, -2) . $deafEndings[$twoChars];
} else {
$word[$key] = mb_substr($value, 0, -2) . $regularEndings[$twoChars];
}
//Если звонкий
} elseif (in_array($thirdChar, $voicedConsonants)) {
if (array_key_exists($twoChars, $voicedEndings)) {
$word[$key] = mb_substr($value, 0, -2) . $voicedEndings[$twoChars];
} else {
$word[$key] = mb_substr($value, 0, -2) . $regularEndings[$twoChars];
}
} elseif (in_array($thirdChar, $vocal)) {
//Получаем окончание из 3 знаков
$threeChars = mb_substr($value, -3);
if (array_key_exists($threeChars, $vocalEndings)) {
$word[$key] = mb_substr($value, 0, -3) . $vocalEndings[$threeChars];
} else {
$word[$key] = mb_substr($value, 0, -2) . $regularEndings[$twoChars];
}
}
} else $word[$key] = "{$value}е";
}
}
}
//Склеиваем обратно и возвращаем
return implode($delimiter[0], $word);
}
//Если навзание простое выполняем склонение в штатном режиме
$singleChar = mb_strtolower(mb_substr($word, -1));
//Если гласная
if (in_array($singleChar, $vocal)) {
$twoChars = mb_strtolower(mb_substr($word, -2));
if (!in_array($twoChars, $noDeclension)) {
if (in_array($twoChars, $endings)) {
//Если окончание присутствует в массиве получаем третий знак
$threeChars = mb_substr($word, -3);
if (in_array($threeChars, $vocalEndings)) {
return mb_substr($word, 0, -3) . $vocalEndings[$threeChars];
}
return mb_substr($word, 0, -2) . $regularEndings[$twoChars];
}
return mb_substr($word, 0, -1) . "е";
}
return $word;
}
//Если согласная
if (in_array($singleChar, $consonants)) {
$twoChars = mb_strtolower(mb_substr($word, -2));
if (!in_array($twoChars, $noDeclension)) {
if (in_array($twoChars, $endings)) {
//Если окончание присутствует в массиве получаем третий знак
$thirdChar = mb_strtolower(mb_substr($word, -3, 1));
if (in_array($thirdChar, $deafConsonants)) {
if (array_key_exists($twoChars, $deafEndings)) {
return mb_substr($word, 0, -2) . $deafEndings[$twoChars];
} else {
return mb_substr($word, 0, -2) . $regularEndings[$twoChars];
}
//Если звонкий
} elseif (in_array($thirdChar, $voicedConsonants)) {
if (array_key_exists($twoChars, $voicedEndings)) {
return mb_substr($word, 0, -2) . $voicedEndings[$twoChars];
} else {
return mb_substr($word, 0, -2) . $regularEndings[$twoChars];
}
}
return mb_substr($word, 0, -2) . $regularEndings[$twoChars];
}
}
return "{$word}е";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment