Conjugate a Turkish verb Input


verb, a string that matches the regular expression ([a-pr-vyzıöüçğş]*[aeıioöuü][bcçdfgğhj-nprsştvyz]+|([a-pr-vyzıöüçğş]*[aeıioöuü]){2})(mak|mek)
plural, a truthy or falsy value
person, an integer having value either 1, 2, or 3
tense, an integer having value either 1, 2, or 3


Output

The conjugated form of the Turkish verb verb, in personst/nd/rd person, plural if plural is TRUE and singular if it is not, in


If tense is 1, the simple present;
If tense is 2, the continuing present;
If tense is 3, the future.


Rules

Turkish verbs are conjugated in three elements, which are in order:


The stem, formed by removing mak or mek from the end of the infinitive;
The sign of the tense, which is:


For the simple present:


  
  -r if the stem ends in a vowel;
  -ir according to vowel harmony rules (see below) if the stem contains more than one syllable (i.e. vowel), or is from one of the following irregular verbs: almak, bilmek, bulmak, durmak, gelmek, görmek, kalmak, olmak, ölmek, sanmak, vermek, varmak, vurmak;
  -er according to vowel harmony rules if the stem contains one syllable and is not listed in the irregular verbs above.
  

For the continuing present, -iyor, where the i changes according to vowel harmony rules. Stems that end in a vowel drop this vowel before adding this suffix, whereupon the suffix harmonizes with the next-to-last vowel in the word (guaranteed to exist by the regular expression).
For the future:


  
  -ecek according to vowel harmony rules if the stem ends in a consonant;
  -yecek according to vowel harmony rules if the stem ends in a vowel.
  


The personal suffix to indicate the performer of the action, in all cases according to vowel harmony rules:

    |Singular|Plural|
|---|--------|------|
|1st|    -im |   -iz|
|2nd|   -sin |-siniz|
|3rd| (none) |  -ler|


The final k of the future tense becomes ğ before -im and -iz, so for example (almak, TRUE, 1, 3) would yield alacağız.


Vowel harmony rules

Turkish vowels are divided into two groups: back (a ı o u) and front (e i ö ü) by where in the mouth they are pronounced. The suffixes of a word change vowels according to the vowels of the root.

All suffixes listed above that have i as a vowel instead use:


-ı if the last vowel before the suffix is ı or a (both these vowels are back and unrounded);
-i if the last vowel before the suffix is i or e (both these vowels are front and unrounded; note here Turkish's distinction between dotted and dotless I);
-u if the last vowel before the suffix is u or o (both these vowels are back and rounded); or
-ü if the last vowel before the suffix is ü or ö (both these vowels are front and rounded).


Take careful note of the present continuous suffix -iyor. The i harmonizes, but the o does not change. The personal suffixes will thus harmonize with the o.

All the suffixes listed above that have e as a vowel instead use:


-e if the last vowel before the suffix is a front vowel; or
-a if the last vowel before the suffix is a back vowel.


Irregular verbs

The verbs gitmek, tatmak, ditmek, gütmek, and etmek change the final t to a d before any endings that begin with a vowel (which includes all the endings in this challenge). Any verb that ends in -etmek likewise changes the t to a d, and appends -er for the simple present (though this is not so for the other verbs).

Test cases

gütmek, FALSE, 1, 2 -&gt; güdüyorum
almak, TRUE, 3, 3 -&gt; alacaklar
boğmak, TRUE, 2, 1 -&gt; boğarsınız
ölmek, FALSE, 3, 1 -&gt; ölür
boyamak, TRUE, 1, 2 -&gt; boyuyoruz
affetmek, FALSE, 2, 1 -&gt; affedersin
söylemek, TRUE, 3, 1 -&gt; söylerler
söylemek, FALSE, 3, 2 -&gt; söylüyor
söylemek, FALSE, 1, 3 -&gt; söyleyeceğim
Javascript (ES6), 466 456 451 446 bytes

(v,p,w,t)=&gt;(R=g=&gt;g.exec(s),T=r=&gt;s=s.slice(0,-1)+r,Z=s=&gt;s.replace(/\d/g,c=&gt;l=['ıuiü'[(n='aıoueiöü'.search(l))&gt;&gt;1],'ae'[n&gt;&gt;2]][c]),(s=v.slice(k=l=0,-3)).replace(/[aıoueiöü]/g,c=&gt;(L=l,l=c,k++)),(R(/^(gi|ta|di|gü)t$/)||(R(/et$/)&amp;&amp;(k=1)))&amp;&amp;T`d`,((E=R(/[aıoueiöü]$/))&amp;&amp;t==2?(l=L,T``):s)+Z([(E?'':k&lt;2&amp;!R(/^((k?a|bi|bu|ge|o|ö)l)|dur|gör|san|v[aeu]r$/))+'r','0yor',(E?'y1c1':'1c1')+'ğkk'[--w]][t-1])+Z('0m|0z|s0n|s0n0z||l1r'.split`|`[w+w+p],t-2||(l='o')))


Ungofled and commented

// Parameters:
//   - 'v' = verb
//   - 'p' = plural flag
//   - 'w' = person
//   - 't' = tense
(v, p, w, t) =&gt; (
  // R() - Helper function to execute a regular expression on the stem.
  R = g =&gt; g.exec(s),

  // T() - Helper function to replace the last character of the stem with 'r'.
  T = r =&gt; s = s.slice(0, -1) + r,

  // Z() - Function that applies vowel harmony to the string 's', assuming
  //       '0' = 'i' and '1' = 'e' and using the last encountered vowel 'l'.
  Z = s =&gt; s.replace(
    /\d/g,
    c =&gt; l = [
      'ıuiü' [(n = 'aıoueiöü'.search(l)) &gt;&gt; 1],
      'ae' [n &gt;&gt; 2]
    ][c]
  ),

  // Computes:
  //   - 's' = stem
  //   - 'k' = number of vowels in stem
  //   - 'l' = last vowel in stem
  //   - 'L' = penultimate vowel in stem
  (s = v.slice(k = l = 0, -3)).replace(/[aıoueiöü]/g, c =&gt; (L = l, l = c, k++)),

  // Applies ending 't' =&gt; 'd' for irregular verbs and those ending in -et(mek).
  (R(/^(gi|ta|di|gü)t$/) || (R(/et$/) &amp;&amp; (k = 1))) &amp;&amp; T `d`,

  // Computes 'E' = truthy value if the stem ends in a vowel.
  // If 'E' is truthy and the tense is the continuing present, drops this vowel.
  ((E = R(/[aıoueiöü]$/)) &amp;&amp; t == 2 ? (l = L, T ``) : s) +

  // Appends sign of tense with vowel harmony.
  Z([
    // t = 1: simple present -&gt; either '-er', '-ir' or '-r'
    (E ? '' : k &lt; 2 &amp; !R(/^((k?a|bi|bu|ge|o|ö)l)|dur|gör|san|v[aeu]r$/) + 'r',

    // t = 2: continuing present -&gt; always '-iyor'
    '0yor',

    // t = 3: future -&gt; either '-yecek', '-ecek', '-yeceğ' or '-eceğ'
    (E ? 'y1c1' : '1c1') + 'ğkk' [--w]
  ][t - 1]) +

  // Appends personal suffix with vowel harmony,
  // forcing last vowel to 'o' for continuing present.
  Z(
    '0m|0z|s0n|s0n0z||l1r'.split `|` [w + w + p],
    t - 2 || (l = 'o')
  )
)


Test cases



let f =
(v,p,w,t)=&gt;(R=g=&gt;g.exec(s),T=r=&gt;s=s.slice(0,-1)+r,Z=s=&gt;s.replace(/\d/g,c=&gt;l=['ıuiü'[(n='aıoueiöü'.search(l))&gt;&gt;1],'ae'[n&gt;&gt;2]][c]),(s=v.slice(k=l=0,-3)).replace(/[aıoueiöü]/g,c=&gt;(L=l,l=c,k++)),(R(/^(gi|ta|di|gü)t$/)||(R(/et$/)&amp;&amp;(k=1)))&amp;&amp;T`d`,((E=R(/[aıoueiöü]$/))&amp;&amp;t==2?(l=L,T``):s)+Z([(E?'':k&lt;2&amp;!R(/^((k?a|bi|bu|ge|o|ö)l)|dur|gör|san|v[aeu]r$/))+'r','0yor',(E?'y1c1':'1c1')+'ğkk'[--w]][t-1])+Z('0m|0z|s0n|s0n0z||l1r'.split`|`[w+w+p],t-2||(l='o')))

console.log(f("gütmek", false, 1, 2));    // -&gt; güdüyorum
console.log(f("almak", true, 3, 3));      // -&gt; alacaklar
console.log(f("boğmak", true, 2, 1));     // -&gt; boğarsınız
console.log(f("ölmek", false, 3, 1));     // -&gt; ölür
console.log(f("boyamak", true, 1, 2));    // -&gt; boyuyoruz
console.log(f("affetmek", false, 2, 1));  // -&gt; affedersin
console.log(f("söylemek", true, 3, 1));   // -&gt; söylerler
console.log(f("söylemek", false, 3, 2));  // -&gt; söylüyor
console.log(f("söylemek", false, 1, 3));  // -&gt; söyleyeceğim