Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine Multiple Regex into One

Tags:

string

regex

php

I am trying to write a code to hyphenate a string into latin verses. There are a few constraints to it which I have taken care of, however I do not get the desired output. My code is given below :

<?php

$string = "impulerittantaenanimis caelestibusirae";

$precedingC = precedingConsonant($string);
$xrule = xRule($precedingC);
$consonantc = consonantCT($xrule);
$consonantp = consonantPT($consonantc);
$cbv = CbetweenVowels($consonantp);
$tv = twoVowels($cbv);

echo $tv;

function twoVowels($string)
{
    return preg_replace('/([aeiou])([aeiou])/', '$1-$2', $string);
}
function CbetweenVowels($string)
{
    return preg_replace('/([aeiou])([^aeiou])([aeiou])/', '$1-$2$3', $string);
}
function consonantPT($string)
{
    return preg_replace('/([^aeiou]p)(t[aeiou])/', '$1-$2', $string);
}
function consonantCT($string)
{
    return preg_replace('/([^aeiou]c)(t[aeiou])/', '$1-$2', $string);
}
function precedingConsonant($string)
{
    $arr1 = str_split($string);
    $length = count($arr1);
    for($j=0;$j<$length;$j++)
    {
        if(isVowel($arr1[$j]) && !isVowel($arr1[$j+1]) && !isVowel($arr1[$j+2]) && isVowel($arr1[$j+3]))
        {
            $pc++;  
        }
    }

    function strAppend2($string)
    {
        $arr1 = str_split($string);
        $length = count($arr1);


        for($i=0;$i<$length;$i++)
        {
            $check = $arr1[$i+1].$arr1[$i+2];
            $check2 = $arr1[$i+1].$arr1[$i+2].$arr1[$i+3];
            if($check=='br' || $check=='cr' || $check=='dr' || $check=='fr' || $check=='gr' || $check=='pr' || $check=='tr' || $check=='bl' || $check=='cl' || $check=='fl' || $check=='gl' || $check=='pl' || $check=='ch' || $check=='ph' || $check=='th' || $check=='qu' || $check2=='phl' || $check2=='phr')
            {
                if(isVowel($arr1[$i]) && !isVowel($arr1[$i+1]) && !isVowel($arr1[$i+2]) && isVowel($arr1[$i+3]))
                {
                    $updatedString = substr_replace($string, "-", $i+1, 0);
                    return $updatedString;
                }
            }
            else
            {
                if(isVowel($arr1[$i]) && !isVowel($arr1[$i+1]) && !isVowel($arr1[$i+2]) && isVowel($arr1[$i+3]))
                {
                    $updatedString = substr_replace($string, "-", $i+2, 0);
                    return $updatedString;
                }
            }
        }
    }
    $st1 = $string;
    for($k=0;$k<$pc;$k++)
    {
        $st1 = strAppend2($st1);
    }

    return $st1;
}
function xRule($string)
{
    return preg_replace('/([aeiou]x)([aeiou])/', '$1-$2', $string);
}
function isVowel($ch)
{
    if($ch=='a' || $ch=='e' || $ch=='i' || $ch=='o' || $ch=='u')
    {
        return true;
    }
    else
    {
        return false;
    }
}
function isConsonant($ch)
{
    if($ch=='a' || $ch=='e' || $ch=='i' || $ch=='o' || $ch=='u')
    {
        return false;
    }
    else
    {
        return true;
    }
}

?>

I believe if I combine all these functions it will result in the desired output. However I will specify my constraints below :

Rule 1 : When two or more consonants are between vowels, the first consonant is joined to the preceding vowel; for example - rec-tor, trac-tor, ac-tor, delec-tus, dic-tator, defec-tus, vic-tima, Oc-tober, fac-tum, pac-tus, 

Rule 2 : 'x' is joined to the preceding vowel; as, rex-i. 

However we give a special exception to the following consonants - br, cr, dr, fr, gr, pr, tr; bl, cl, fl, gl, pl, phl, phr, ch, ph, th, qu. These consonants are taken care by adding them to the later vowel for example - con- sola-trix
n- sola-trix. 

Rule 3 : When 'ct' follows a consonant, that consonant and 'c' are both joined to the first vowel for example - sanc-tus and junc-tum

Similarly for 'pt' we apply the same rule for example - scalp-tum, serp-tum, Redemp-tor. 

Rule 4 : A single consonant between two vowels is joined to the following vowel for example - ma-ter, pa-ter AND Z is joined to the following vowel. 

Rule 5 : When two vowels come together they are divided, if they be not a diphthong; as au-re-us. Diaphthongs are - "ae","oe","au"
like image 204
Aaditya Damani Avatar asked Oct 12 '16 19:10

Aaditya Damani


1 Answers

If you look carefully at each rule, you can see that all involve a vowel at the beginning or a preceding vowel. Once you realize that, you can try to build a single pattern putting [aeiou] in factor at the beginning:

$pattern = '~
    (?<=[aeiou]) # each rule involves a vowel at the beginning (also called a
                 # "preceding vowel")
    (?:
        # Rule 2: capture particular cases
        ( (?:[bcdfgpt]r | [bcfgp] l | ph [lr] | [cpt] h | qu ) [aeiou] x )
      |
        [bcdfghlmnp-tx]
        (?:
            # Rule 3: When "ct" follows a consonant, that consonant and "c" are both
            # joined to the first vowel
            [cp] \K (?=t)
          |
            # Rule 1: When two or more consonants are between vowels, the first
            # consonant is joined to the preceding vowel
            \K (?= [bcdfghlmnp-tx]+ [aeiou] )
        )   
      |
        # Rule 4: a single consonant between two vowels is joined to the following
        # vowel
        (?:
            \K (?= [bcdfghlmnp-t] [aeiou] )
          | 
            # Rule 2: "x" is joined to the preceding vowel
            x \K (?= [a-z] | (*SKIP)(*F) ) 
        )
      |
        # Rule 5: When two vowels come together they are divided, if they not be a
        # diphthong ("ae", "oe", "au")
        \K (?= [aeiou] (?<! a[eu] | oe ) )
    )
~xi';

This pattern is designed to only match the position where to put the hyphen (except for particular cases of Rule 2), that's why it uses a lot of \K to start the match result at this position and lookaheads to test what follows without matching characters.

$string = <<<EOD
Aeneadum genetrix, hominum diuomque uoluptas,
alma Uenus, caeli subter labentia signa
quae mare nauigerum, quae terras frugiferentis
concelebras, per te quoniam genus omne animantum
EOD;

$result = preg_replace($pattern, '-$1', $string);

Ae-ne-a-dum ge-ne-trix, ho-mi-num di-u-om-qu-e u-o-lup-tas,
al-ma U-e-nus, cae-li sub-ter la-ben-ti-a sig-na
qu-ae ma-re nau-i-ge-rum, qu-ae ter-ras fru-gi-fe-ren-tis
con-ce-leb-ras, per te qu-o-ni-am ge-nus om-ne a-ni-man-tum

Note that I didn't include several letters like k, y and z that don't exist in the latin alphabet, feel free to include them if you need to handle translated greek words or other.

like image 61
Casimir et Hippolyte Avatar answered Sep 28 '22 06:09

Casimir et Hippolyte