16
\$\begingroup\$

Read this yng Nghymraeg

Challenge

Given a word in Welsh, output all of the possible mutated forms of the word.

Mutations

A mutation is a change of the first letter of a word when following certain words or in certain grammatical contexts.

In Welsh, the following are considered "consonants":

b c ch d dd f ff g ng h l ll m n p ph r rh s t th

Note that multiple character consonants such as ch, ng and rh are counted as one letter in Welsh, and therefore one consonant.

The other letters in the Welsh alphabet are vowels, listed below:

a e i o u w y

See below, all of the mutations with the original letter on the left and the resulting mutated letters on the right:

Original | Mutations
---------+---------------
p        | b mh ph
t        | d nh th
c        | g ngh ch
b        | f m
d        | dd n
g        | [no letter] ng
m        | f
ll       | l
rh       | r

Here, [no letter] means that the g is removed from the start of the word.

Note that there are some consonants which do not mutate:

ch
dd
f
ff
j
l
n
ng
ph
r
s
th

Vowels may also be found at the start of words but do not mutate:

a
e
i
o
u
w
y

Examples

Input: dydd

Output:

dydd
ddydd
nydd

Input: pobl

Output:

pobl
bobl
mhobl
phobl

Input: gwernymynydd

Output:

gwernymynydd
wernymynydd
ngwernymynydd

Input: ffrindiau

Output:

ffrindiau

Input: enw

Output:

enw

Input: theatr

Output:

theatr

On the request of ArtOfCode ;)

Input: llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch

Output:

llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch
lanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch

Rules

The input will only ever be one word.

There will always be more letters after the leading consonant in your input.

Winning

The shortest code in bytes wins.

\$\endgroup\$
6
  • 5
    \$\begingroup\$ New test case: llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch \$\endgroup\$
    – ArtOfCode
    Commented Sep 10, 2016 at 8:01
  • \$\begingroup\$ Another test case theatr; t mutates but th doesn't. \$\endgroup\$ Commented Sep 10, 2016 at 9:32
  • \$\begingroup\$ Should be 'Golff y Côd' - 'yr' only comes before a vowel, you use 'y' before a consonant. \$\endgroup\$
    – Gareth
    Commented Sep 10, 2016 at 12:25
  • \$\begingroup\$ If anyone's interested in the complicated rules regarding mutation in Welsh, there's an app called 'Ap Treiglo' which gives the rules and lists many of the words which cause mutations in the following word. \$\endgroup\$
    – Gareth
    Commented Sep 10, 2016 at 12:38
  • \$\begingroup\$ @Beta Decay Yeah, for the last 5 years. Rhyl before that, for my sins. \$\endgroup\$
    – Gareth
    Commented Sep 10, 2016 at 20:02

6 Answers 6

5
\$\begingroup\$

JavaScript (ES6), 180 bytes

x=>x.replace(/^([cpt](?!h)|d(?!d)|[bgm]|ll|rh)(.+)/,(_,y,z)=>({p:"b mh ph",t:"d nh th",c:"g ngh ch",b:"f m",d:"dd n",g:" ng",m:"f"}[y]||y[0]).split` `.map(b=>a.push(b+z)),a=[x])&&a

Outputs as an array of strings. This is my first try, so it's almost certainly not optimal.

Try it out

f=x=>x.replace(/^([cpt](?!h)|d(?!d)|[bgm]|ll|rh)(.+)/,(_,y,z)=>({p:"b mh ph",t:"d nh th",c:"g ngh ch",b:"f m",d:"dd n",g:" ng",m:"f"}[y]||y[0]).split` `.map(b=>a.push(b+z)),a=[x])&&a
<input id=A value="pobl"><button onclick="B.innerHTML=f(A.value).join('<br>')">Run</button><br>
<pre id=B>

\$\endgroup\$
1
  • \$\begingroup\$ It's not optimal, but my PC decided to switch itself off, and I no longer remember what optimisation I was able to make. \$\endgroup\$
    – Neil
    Commented Sep 11, 2016 at 0:29
4
\$\begingroup\$

C#, 356 338 360 bytes

I know that C# is a poor choice for code golf, but it's worth the shot:

Third attempt, all cases now pass, including th- ph- etc. This adjustment cost roughly 18 bytes.

Thanks pinkfloydx33 for the tips saving 24 bytes!

namespace System{using Linq;using S=String;class P{static void Main(S[]a){Action<S>w=Console.WriteLine;w(a[0]);foreach(S r in"th-dd-ch-ph-p.b.mh.ph-t.d.nh.th-c.g.ngh.ch-b.f.m-d.dd.n-g..ng-m.f-ll.l-rh.r".Split('-')){var b=r.Split('.');if(a[0].StartsWith(b[0])){foreach(S f in b.Skip(1))w(Text.RegularExpressions.Regex.Replace(a[0],$"^{b[0]}",f));break;}}}}}

Output

$> ./p gwernymynydd
gwernymynydd
wernymynydd
ngwernymynydd

Formatted Version

    namespace System {
    using Linq;
    using S = String;

    class P {
        static void Main(S[] a) {
            Action<S> w = Console.WriteLine;
            w(a[0]);
            foreach (S r in "th-dd-ch-ph-p.b.mh.ph-t.d.nh.th-c.g.ngh.ch-b.f.m-d.dd.n-g..ng-m.f-ll.l-rh.r"
                .Split('-')) {
                var b = r.Split('.');
                if (a[0].StartsWith(b[0])) {
                    foreach (S f in b.Skip(1))
                        w(Text.RegularExpressions.Regex.Replace(a[0], $"^{b[0]}", f));
                    break;
                }
            }
        }
    }
}
\$\endgroup\$
6
  • 1
    \$\begingroup\$ $"{f}" should just be f, you can also save the first call to write line, as well as the action, by not skipping the first element in b (saving the skip as well) and just replacing the first item with itself (I think). You also only make one call to regex so Caching/renaming the import costs more than just Text.RegularExpressions.Regex.Replace(...) in the body. The break is also superfluous since it's only gonna match once doesnt matter if it loops through to the end \$\endgroup\$ Commented Sep 10, 2016 at 3:08
  • 1
    \$\begingroup\$ There are no poor choices of language for golf - you are competing against anyone else who wants to try and beat you in the same language. Plus C# was once the golfing language of choice for Jon Skeet... \$\endgroup\$ Commented Sep 10, 2016 at 8:32
  • \$\begingroup\$ @pinkfloydx33 Thanks for the tips! However I can't remove the first Console.WriteLine call because this will skip outputting the word in case there are no replacements for it. I am sure there is a way how to optimize it by changing the condition. \$\endgroup\$
    – grizzly
    Commented Sep 10, 2016 at 17:06
  • \$\begingroup\$ I just spotted theatr case and it seems it isn't mutating correctly. \$\endgroup\$
    – grizzly
    Commented Sep 10, 2016 at 17:07
  • \$\begingroup\$ Yeah there are several test cases that don't pass at the moment because PH, TH, CH and DD do not get transformed \$\endgroup\$ Commented Sep 10, 2016 at 17:59
3
\$\begingroup\$

Python 3, 196,189 185 bytes

Original attempt

w=input();print(w);[w.startswith(a)and[print(w.replace(a,i,1))for i in
r]+exit()for(a,*r)in(j.split(',')for j
in'th rh ph p,b,mh,ph t,d,nh,th c,g,ngh,ch b,f,m d,dd,n g,,ng m,f ll,l rh,r'.split())]

Vaultah noted that not w.find(a) would be a replacement for w.startswith(a) that would save 2 characters. But instead of not x and y we can use x or y which saves some characters more:

w=input();print(w);[w.find(a)or[print(w.replace(a,i,1))for i in
r]+exit()for(a,*r)in(j.split(',')for j
in'th rh ph p,b,mh,ph t,d,nh,th c,g,ngh,ch b,f,m d,dd,n g,,ng m,f ll,l rh,r'.split())]

Yet further savings by replacing w.replace(a,i,1) with i+w[len(a):]:

w=input();print(w);[w.find(a)or[print(i+w[len(a):])for i in
r]+exit()for(a,*r)in(j.split(',')for j
in'th rh ph p,b,mh,ph t,d,nh,th c,g,ngh,ch b,f,m d,dd,n g,,ng m,f ll,l rh,r'.split())]

Then I noticed that there was a bug, rh was listed twice; once in my short-circuit list that would take care of those double-letter consonants. Unfortunately dd was missing from there, so no savings, and we have

w=input();print(w);[w.find(a)or[print(i+w[len(a):])for i in
r]+exit()for(a,*r)in(j.split(',')for j
in'th ph dd p,b,mh,ph t,d,nh,th c,g,ngh,ch b,f,m d,dd,n g,,ng m,f ll,l rh,r'.split())]

Given any of the sample inputs, it gives the desired output; given

gorsaf

it outputs

gorsaf
orsaf
ngorsaf

and given input

theatr

it prints

theatr
\$\endgroup\$
3
\$\begingroup\$

PowerShell v3+, 254 231 bytes

param($a)$a;$z=-join$a[1..$a.length]
if(($x=@{112='b mh ph';116='d nh th';99='g ngh ch';98='f m';100='dd n';109='f'})[+$a[0]]-and$a-notmatch'^[cpt]h|^dd'){-split$x[+$a[0]]|%{"$_$z"}}
($z,"ng$z")*($a[0]-eq103)
$z*($a-match'^ll|^rh')

working to golf further...

Examples

(Output is space-separated because that's the default Output Field Separator for stringified arrays. I don't know if the words I used for testing are actual words, but they fit the exceptions.)

PS C:\Tools\Scripts\golfing> 'dydd','pobl','gwernymynydd','ffrindiau','enw','rhee','llewyn','chern','ddydd','phobl'|%{"$_ --> "+(.\golff-yr-cod.ps1 $_)}
dydd --> dydd ddydd nydd
pobl --> pobl bobl mhobl phobl
gwernymynydd --> gwernymynydd wernymynydd ngwernymynydd
ffrindiau --> ffrindiau
enw --> enw
rhee --> rhee hee
llewyn --> llewyn lewyn
chern --> chern
ddydd --> ddydd
phobl --> phobl
\$\endgroup\$
1
\$\begingroup\$

C#, 349 bytes

Based on @grizzly's submission, but corrected to work with the consonants that don't get transformed (ph/ch/th/dd) that it wasn't working with, plus trimmed some excess out. Hope that's alright?

I had it down to 290 until I realized that I was missing the th/ch/ph/dd cases :-(. Adding in the Regex call killed it

namespace System{class P{static void Main(string[]a){var x=a[0];if(!Text.RegularExpressions.Regex.IsMatch(x,"^[pct]h|^dd"))foreach(var r in"p.b.mh.ph-t.d.nh.th-c.g.ngh.ch-b.f.m-d.dd.n-g..ng-m.f-ll.l-rh.r".Split('-')){var b=r.Split('.');if(a[0].StartsWith(b[0]))for(int i=1;i<b.Length;)x+='\n'+b[i++]+a[0].Substring(b[0].Length);}Console.Write(x);}}}

Interesting note, never knew that you could omit the space between var r in"string"

Formatted:

namespace System
{
    class P
    {
        static void Main(string[] a)
        {
            var x = a[0];
            if (!Text.RegularExpressions.Regex.IsMatch(x, "^[pct]h|^dd"))
                foreach (var r in"p.b.mh.ph-t.d.nh.th-c.g.ngh.ch-b.f.m-d.dd.n-g..ng-m.f-ll.l-rh.r".Split('-'))
                {
                    var b = r.Split('.');
                    if (a[0].StartsWith(b[0]))
                        for (int i = 1; i < b.Length;) x += '\n' + b[i++] + a[0].Substring(b[0].Length);
                }
            Console.Write(x);
        }
    }
}
\$\endgroup\$
1
\$\begingroup\$

Perl 6, 162 bytes

{/^(.|<[cprt]>h|dd|ff|ng|ll)(.*)/;(%('p',<b mh ph>,'t',<d nh th>,'c',<g ngh ch>,'b',<f m>,'d',<dd n>,'g',«'' ng»,'m',<f>,'ll',<l>,'rh',<r>){$0}//~$0).map(*~$1)}

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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