# C++ 14 (g++), <s>181</s> <s>171</s> 148 bytes <!-- language-all: lang-c++ --> [](auto s){s[0]&=~32;int i=1,n=s.length()-1,b;for(;s[i];)s[i++]|=32;b=s[n]-'y';return s+(b?"y":"")+" Mc"+(b?s:s.substr(0,s[n-1]-'e'?n:n-1))+"face";} Note that clang will not compile this. Credit goes to [Kevin Cruijssen][1] for the `&~32` trick and for helping me shave off 10 bytes. Try it online [here][2]. Ungolfed version: [] (auto s) { // lambda s[0] &= ~32; // convert the first character to upper case int n = s.length()-1, // the position of the last character i = 1, // for iterating over the string b; // we'll need this later for(; s[i] ;) // iterate over the rest of the string s[i++] |= 32; // converting it to lower case b = s[n] - 'y'; // whether the last character is not a 'y' return s + (b ? "y" : "") // append 'y' if not already present + " Mc" + (b ? s : s.substr(0, s[n-1] - 'e' ? n-1 : n)) // remove one, two, or zero chars from the end depending on b and whether the second to last character is 'e' + "face"; } [1]: https://codegolf.stackexchange.com/a/160529/79343 [2]: https://tio.run/##dY9Rb4IwFIWfx69oumS2QYxub1Tmy6KJmdneGTGlVG0GxdDyQJz766wtZlmy8sK9nNPvnnvZ@RwdGetpq2tQgQT0aYbcj8IXlc6zh@T76ZEIqYFIFlOZqFnJ5VGfEI4W05wc6gYRlYqMYPMNw@wrMc/zRKUyiybdhDRct40EKkT5CnYwhhCHEOwYtIKK1Uy1udINmk8NEi0MxCcrGZsWm4cHyjgk154Ewb2QrGwLDpaiNgCn1XNQUSERBpfgTukijo0s5BHkNdXmEmgrJDeP1a0GyyWokJWxbeGH/LVv6NrkWXTtcv@hVh5DX942ljTFAxp1PLISZTeE2s4ba42xAa@0cLitHtjKozvX8pM7eOh8mztjbMB7STve2AFD5xkwGGMDus7Fm@JBjTq6@Xa/aags9juqNG/265KqkztkC5wBBgM4w3eXb8CftGv/Aw