An Séimhiú agus an tUrú

In Irish Gaelic (Gaeilge) there are a number of ways that the start of a word can be changed. The most common of these are lenition (an séimhiú) and eclipsis (an t-urú)

Lenition involves adding the letter h as the second letter. For example, the word "bean" (woman) would be lenited to "bhean".

Eclipsing adds a prefix to the word. The prefix is determined by the first letter of the word. For example, the word "capall" (horse) starts with a c. Its eclipsis is g. So when the word "capall" is eclipsed it becomes "gcapall".


Write a function or program that takes a word and returns both its lenited and eclipsed forms.


Only words beginning with:


are lenited. Words beginning with other letters are not changed.

Some examples:

bean       bhean
capall     chapall
Sasana     Shasana
lón        lón
Ífreann    Ífreann


If a word starts with any of the following letters, it is prefixed by its respective eclipsis:

Letter   Eclipsis
b        m
c        g
d        n
f        bh
g        n
p        b
t        d

Words that don't start with those letters remain unchanged.


bean        mbean
capall      gcapall
cailín      gcailín
doras       ndoras
fuinneog    bhfuinneog
Gaeilge     nGaeilge
Sasana      Sasana

There are other changes that can happen to the start of a word, but we'll just focus on these ones.


The input is only one word. Words will only contain a-z, A-Z or the fada vowels á, Á, é, É, í, Í, ó, Ó, ú and Ú.

To make it a bit more simple the word itself doesn't necessarily need to be an Irish word, just that it is treated like one in the code. So inputting delta should return dhelta and ndelta.

For this challenge you can assume that the input words have not already been lenited or eclipsed (in Irish, a word is only lenited or eclipsed once. You would never end up with "bhhean" or "ngcapall").

Standard rules apply, including the default I/O rules. Similarly, default loopholes are forbidden.

Finally, this is so shortest answer in bytes wins.

Test cases

Input      Lenited     Eclipsed
bean       bhean       mbean
capall     chapall     gcapall
fuinneog   fhuinneog   bhfuinneog
Sasana     Shasana     Sasana
Gaeilge    Ghaeilge    nGaeilge
lón        lón         lón
áthas      áthas       áthas
Ífreann    Ífreann     Ífreann
  • \$\begingroup\$ Sandbox post. \$\endgroup\$ – Ciaran_McCarthy Jan 8 '19 at 9:49
  • \$\begingroup\$ Yes, for example Ífreann or áthas. In those cases, however, you would not change the word. \$\endgroup\$ – Ciaran_McCarthy Jan 8 '19 at 12:02
  • \$\begingroup\$ what does the title mean? \$\endgroup\$ – Giuseppe Jan 8 '19 at 15:44
  • 2
    \$\begingroup\$ "(The) Lenition and (the) Eclipsis". I'm not a fluent speaker, so I don't know if it's correct to specify them with the definite article (an). Séimhiú is lenition and urú is eclipsis. In the title Urú takes a 't' at the start, because it starts with a vowel and is preceded by the definite article. When it's a capital letter there's no hyphen between them. Hence: "There are other changes that can happen to the start of a word, but we'll just focus on these ones." \$\endgroup\$ – Ciaran_McCarthy Jan 8 '19 at 16:43
  • 1
    \$\begingroup\$ "but you would" ... the suspense is killing me! \$\endgroup\$ – Sparr Jan 10 '19 at 18:57

13 Answers 13


Perl 6, 83 77 bytes

-6 bytes thanks to Jo King

{S:i/^<[bcdfgmpst]>/$/h/,{S/0/bh/}({$_ x tr/dbcfptg/nmg0bd/}($= m/./.lc))~$_}

Try it online!

Returns a two-element list.

|improve this answer|||||

05AB1E, 45 44 bytes

.•1˜3WÓƵ•sнlk©diн'hI¦JI®7‹i.•B}в •S„bhš®èì]‚

Ended up longer than I anticipated beforehand.. Can probably be golfed some more, though.

Try it online or verify all test cases.


.•1˜3WÓƵ•                   # Push compressed string "fbcdgptms"
s                           # Swap to take the (implicit) input-string
 н                          # Get its first character
  l                         # Convert it to lowercase
   k                        # Get the index in the string (-1 if not found)
    ©                       # Store it in the register (without popping)
     di                     # If the index is non-negative (>= 0):
       н                    #  Get the first character of the (implicit) input-string again
        'h                 '#  Push a "h"
          I                 #  Push the input
           ¦                #  And remove its first character
            J               #  Join all three strings together
       I                    #  Then push the input-string again
        ®7‹i                #  If the index from the register is smaller than 7:
            .•B}в •         #   Push compressed string "mgnnbd"
                   S        #   As a list of characters: ["m","g","n","n","b","d"]
                    „bhš    #   And prepend "bh" to this list: ["bh","m","g","n","n","b","d"]
                        ®è  #   Then use the index from the register in this list
                          ì #   And prepend it in front of the input-string
      ]                     # Close both if-statements
       ‚                    # Pair the two strings at the top of the stack
                            # (uses the input implicitly if we haven't entered the first if)
                            # (and output this pair of strings implicitly)

See this 05AB1E tips of mine (section How to compress strings not part of the dictionary?) to understand why .•1˜3WÓƵ• is "fbcdgptms" and .•B}в • is "mgnnbd".

Alternative for .•B}в •S„bhš with the same byte-count can be .•„Å'Àāʈѕ#, where .•„Å'Àāʈѕ is the compressed string "bh m g n n b d" and # will split on spaces.

|improve this answer|||||

JavaScript (ES6),  98  97 bytes

Returns an array [lenited, eclipsed].


Try it online!


We define the following lookup table:

A = [ ...'2n1111gbnd1m1', 'bh', 2 ]

//     0    1    2    3    4    5    6    7    8    9    10   11   12   13  14
A = [ '2', 'n', '1', '1', '1', '1', 'g', 'b', 'n', 'd', '1', 'm', '1', 'bh', 2 ]


  • a single character (or the string "bh") is used for eclipsis; all letters that trigger eclipsis also trigger lenition
  • \$1\$ means that there's no eclipsis and no lenition
  • \$2\$ means that there's no eclipsis but there is lenition

The first letter of the input word is converted from Base30 to decimal, multiplied by \$17\$ and then reduced with a modulo \$22\$. The result is used to pick the correct value from \$A\$.

Any result above \$14\$ yields undefined, and so does any letter in the range u-z or any fada vowel. An undefined value is interpreted the same way as \$1\$ (no eclipsis, no lenition).

  1st letter | from Base30 | * 17 | mod 22 | A[n]
      a      |      10     |  170 |   16   | undefined
      b      |      11     |  187 |   11   | 'm'
      c      |      12     |  204 |    6   | 'g'
      d      |      13     |  221 |    1   | 'n'
      e      |      14     |  238 |   18   | undefined
      f      |      15     |  255 |   13   | 'bh'
      g      |      16     |  272 |    8   | 'n'
      h      |      17     |  289 |    3   | '1'
      i      |      18     |  306 |   20   | undefined
      j      |      19     |  323 |   15   | undefined
      k      |      20     |  340 |   10   | '1'
      l      |      21     |  357 |    5   | '1'
      m      |      22     |  374 |    0   | '2'
      n      |      23     |  391 |   17   | undefined
      o      |      24     |  408 |   12   | '1'
      p      |      25     |  425 |    7   | 'b'
      q      |      26     |  442 |    2   | '1'
      r      |      27     |  459 |   19   | undefined
      s      |      28     |  476 |   14   | 2
      t      |      29     |  493 |    9   | 'd'
 u-z or fada |     NaN     |  NaN |  NaN   | undefined
|improve this answer|||||

Python 3, 100 bytes

lambda w,l='bBcCdDgGpPtTfF':(w[0]+'h'*(w[0]in'msMS'+l)+w[1:],[*'mgnnbd','bh',''][l.find(w[0])//2]+w)

Try it online!

-3 thanks to Black Owl Kai.

|improve this answer|||||

Stax, 41 bytes


Run and debug it

|improve this answer|||||

Java 10, 140 135 bytes

s->{var h=s.charAt(0);int i="fbcdgptms".indexOf(h|32);return(i<0?s:h+"h"+s.substring(1))+" "+",bh,m,g,n,n,b,d,,".split(",",10)[i+1]+s;}

Port of my 05AB1E answer.
-5 bytes thanks to @OlivierGrégoire.

Try it online.


s->{                              // Method with String as both parameter and return-type
  var h=s.charAt(0);              //  Get the first character of the input
  int i="fbcdgptms".indexOf(h     //  Get its index in the string "fbcdgptms"
                            |32); //  After converting it to lowercase
  return(i<0?                     //  If the index is -1 (not found):
          s                       //   Return the input unchanged
         :                        //  Else:
          h                       //   Return the first character
          +"h"                    //   Appended with an "h"
          +s.substring(1))        //   Appended with the rest of the string
         +" "                     //  Then append a space delimiter
                                  //  Push {"","bh","m","g","n","n","b","d","",""}
          [i+1]                   //  and append the character at index `i+1`
         +s;}                     //  And append the input-string
|improve this answer|||||
  • 1
    \$\begingroup\$ 135 bytes: s->{var h=s.charAt(0);int i="fbcdgptms".indexOf(h|32);return(i<0?s:h+"h"+s.substring(1))+" "+" bh m g n n b d ".split(" ",10)[i+1]+s;} \$\endgroup\$ – Olivier Grégoire Jan 9 '19 at 14:43
  • \$\begingroup\$ @OlivierGrégoire Ah, smart use of ",bh,m,g,n,n,b,d,,".split(",",10)[i+1] (I've changed the spaces to commas, since it's a bit more readable)! Would have never thought about that. \$\endgroup\$ – Kevin Cruijssen Jan 9 '19 at 14:57

C# (Visual C# Interactive Compiler), 151 bytes

x=>{var p=(char)(x[0]%32+96);return(x.Insert(1,(a+"ms").Contains(p)?"h":""),p==102?"bh"+x:"mgnnbd "[a.IndexOf(p)<0?6:a.IndexOf(p)]+x);};var a="bcdgpt";

It's really long, and there are probably ways to golf it more. But I'm just too lazy.

Try it online!

|improve this answer|||||
  • \$\begingroup\$ Your answer only covers lowercase inputs, so Gaeilge is for example incorrect. PS: Since you only use b once, you can golf string a="bcdgpt",b="mgnnbd "; to var a="bcdgpt"; and b[ to "mgnnbd "[. \$\endgroup\$ – Kevin Cruijssen Jan 9 '19 at 13:16
  • \$\begingroup\$ @Kevin Cruijssen Fixed \$\endgroup\$ – Embodiment of Ignorance Jan 9 '19 at 21:00
  • \$\begingroup\$ Nice, +1 from me. Two small things to golf: put the var a="bcdgpt"; inside the method, because you don't have to count the trailing semi-colon of lambda functions. And you can change the %32+96 to |32 to convert to lowercase. Try it online 147 bytes \$\endgroup\$ – Kevin Cruijssen Jan 9 '19 at 21:35
  • \$\begingroup\$ Yeah, I forgot about that last string.Thanks! \$\endgroup\$ – Embodiment of Ignorance Jan 9 '19 at 21:45

C# (.NET Core), 165, 131, 126 bytes

Edit: ASCII-only with -34 bytes. Puts everything into one string.

Edit2: Kevin Cruijssen with the 5 byte golf to ToUpper()!

p=>{var s="BCDFGMPSTMGN N B D";var k=s.IndexOf(p.ToUpper()[0]);return(p.Insert(1,k<0?"":"h"),k<0?p:s[k]==70?"bh"+p:s[k+9]+p);}

Try it online!

|improve this answer|||||
  • 2
    \$\begingroup\$ 131 \$\endgroup\$ – ASCII-only Jan 10 '19 at 12:39
  • 1
    \$\begingroup\$ 126 bytes Removed the +p.ToUpper() from the string s, so you can use p.ToUpper()[0] and k<0 instead of s[18] and k>17. \$\endgroup\$ – Kevin Cruijssen Jan 10 '19 at 14:38

PowerShell, 121 122 116 98 Bytes

-24 bytes thanks to @mazzy


Try it online!

Uses a simple regex for the lenition and a switch statement far superior hashtable thanks to @mazzy for the eclipsis. This can probably get a lot shorter.

|improve this answer|||||
  • \$\begingroup\$ maybe you should think about: 1) replace a first letter only, 2) switch as expression $(switch -r($a[0]){'b'{'m'}'c'{'g'}....})+$a, 3) hashtable instead the switch. \$\endgroup\$ – mazzy Jan 9 '19 at 6:29
  • \$\begingroup\$ Thanks, @mazzy, but I'm not sure how to use a hashtable in this situation. Could you give me an idea of what this might look like? \$\endgroup\$ – Gabriel Mills Jan 9 '19 at 21:45
  • \$\begingroup\$ param($a)$a-replace'^[bcdfgmpst]','$&h';@{b='m';c='g';d='n';g='n';f='bh';p='b';t='d'}[''+$a[0]]+$a \$\endgroup\$ – mazzy Jan 10 '19 at 5:39

Perl 6, 101 bytes

{.subst(/:i ^<[bcdfgmpst]>/,{$_~'h'}),.subst(/^./,{(%(<b m c g d n f bh g n p b t d>){.lc}//'')~$_})}

Try it online!

|improve this answer|||||

Retina 0.8.2, 77 bytes


Try it online! Link includes test cases. Explanation:


If the word can be lenited, create the lenition, and make a copy for the eclipsis with a duplicate first letter.


Lowercase the duplicate letter.


If it's an f then change it to ph; it will get fixed to bh later.


Fix or remove the eclipsis (m and s have a lentition but no eclipsis).


If there was no lentition then duplicate the word anyway.

|improve this answer|||||

Python 3, 118 bytes

def f(w):a=w[0].lower();return w[0]+'h'*(a in'ms'+s)+w[1:],dict(zip(s,'bmgnnbd')).get(a,'')+'h'*(a=='f')+w

Try it online!

|improve this answer|||||
  • \$\begingroup\$ I'm afraid it returns the wrong elipses for 'bean', 'capall' and 'fuinneog'. \$\endgroup\$ – Ciaran_McCarthy Jan 9 '19 at 10:14
  • 1
    \$\begingroup\$ @Ciaran_McCarthy Fixed \$\endgroup\$ – TFeld Jan 9 '19 at 10:49

JAVASCRIPT 131 bytes

Implementing Kevin Cruijssen answer in javaScript:

(w,i='bcdfgmpst'.indexOf(w.toLowerCase()[0]))=>(i>=0?[w,w[0]+'h'+w.substr(1),'m,g,n,bh,n,,b,,d'.split(',')[i]+w]:[w,w,w]).join(' ')
 w,                                                          // the input (string)
 i='bcdfgmpst'.indexOf(w.toLowerCase()[0])                   // the index of the lenited word
i>=0?                                                        // if index greater or equals 0
 [w,w[0]+'h'+w.substr(1),'m,g,n,bh,n,,b,,d'.split(',')[i]+w] // return Array(input, lenited, eclipsis) 
:                                                            // else
 [w,w,w]                                                     // return Array(input, input, input)
).join(' ')                                                  //Join array items with spaces
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.