Facey McFaceface

48

8

Anyone remember Boaty?

You could totally make any old word, right?

  • Write a function to turn a string into Somethingy McSomethingface.
  • It should accept one string as input. Ignore the case of the input.
  • If the word ends in 'y', your function should not add an additional 'y' to the first instance, but should remove it in the second instance.
  • If the word ends in 'ey', it should not have an additional 'y' added in the first instance, but should remove both in the second instance.
  • The output should only have upper case letters in the first character, the 'M' of 'Mc' and the first character after 'Mc'.
  • it only needs to work with strings of 3 or more characters.

Examples:

boat                  =>  Boaty McBoatface
Face                  =>  Facey McFaceface
DOG                   =>  Dogy McDogface
Family                =>  Family McFamilface
Lady                  =>  Lady McLadface
Donkey                =>  Donkey McDonkface
Player                =>  Playery McPlayerface
yyy                   =>  Yyy McYyface
DJ Grand Master Flash =>  Dj grand master flashy McDj grand master flashface

AJFaraday

Posted 2018-03-27T15:59:47.357

Reputation: 10 466

What about spaces in the string, do we leave them intact? Examples: ' y' and ' ' – touch my body – 2018-03-27T17:02:19.613

2I’m going to implement a suggestion from @Arnauld and make it three characters minimum. Treat whitespace just like another letter. – AJFaraday – 2018-03-27T17:04:05.600

Related: Code Johnny Code, Code! – Kevin Cruijssen – 2018-03-28T09:42:20.700

Can we assume the input will only contain upper and lowercase letters? – Kevin Cruijssen – 2018-03-28T13:16:00.483

@KevinCruijssen I haven't put any non-letters in the test cases, so they're effectively not concerned. – AJFaraday – 2018-03-28T13:17:42.143

@AJFaraday That's what I said... And regardless of what characters are in the test cases, you should clarify whether the input will contain non-letters, since a lot of commenters assume it may contain whitespace. – James – 2018-03-28T13:32:58.613

@DJMcMayhem Ahhh, good point. I've assumed whitespace is fine and that's been factored in to a lot of answers. I should have a test case for it. Probably DJ Grand Master Flash => Dj grand master flashy McDj grand master flashface – AJFaraday – 2018-03-28T13:34:35.800

Donkey McDonkface is my favorite... seems like it would make a great insult. – NH. – 2018-03-28T16:22:55.033

This has to be the best function ever. – Three Diag – 2018-03-29T14:40:56.270

Nitpick: shouldn't that be Doggy McDogface? – craq – 2018-03-29T18:16:14.700

@craq I thought of that, but too late, unfortunately. It’s hard to change it after people have answered. – AJFaraday – 2018-03-29T18:54:03.227

Spaces in the input seem to break answers that rely on title-casing the input. – user41805 – 2018-03-30T16:16:58.910

@Cowsquack if they pass my test cases, I declare them successful. – AJFaraday – 2018-03-30T17:24:23.973

Answers

7

Stax, 26 bytes

ëO╛εh╕⌠î&!}∞┌C^U╟«äδ◙Bg⌠└¿

Run and debug it

^           convert input to upper case                     "FACE"
B~          chop first character and push it back to input  70 "ACE"
v+          lowercase and concatenate                       "Face"
c'yb        copy, push "y", then copy both                  "Face" "Face" "y" "Face" "y"
:]          string ends with?                               "Face" "Face" "y" 0
T           trim this many character                        "Face" "Face" "y"
+           concatenate                                     "Face" "Facey"
p           output with no newline                          "Face"
"e?y$"z     push some strings                               "Face" "e?y$" ""
" Mc`Rface  execute string template; `R means regex replace " Mc Faceface"
            result is printed because string is unterminated

Run this one

recursive

Posted 2018-03-27T15:59:47.357

Reputation: 8 616

15

V, 27 28 30 bytes

Vu~Ùóe¿y$
Hóy$
ÁyJaMc<Esc>Aface

Try it online!

<Esc> represents 0x1b

  • Golfed two bytes after learning that we did not need to support inputs with less than 3 characters.

  • 1 byte saved thanks to @DJMcMayhem by working on the second line before the first one, thus removing the G

The input is in the buffer. The program begins by converting everything to lowercase

V selects the line and u lowercases it

~ toggles the case of the first character (converting it to uppercase)

and Ù duplicates this line above, leaving the cursor at the bottom line

ó and replaces e¿y$, compressed form of e\?y$ (optional e and a y at the end of the line), with nothing (happens on the second line)

H goes to the first line

ó replaces y$ (y at the end of the line) with nothing on the first line

Á appends a y to the end of the first line

J and joins the last line with the first with a space in the middle, and the cursor is moved to this space

a appends Mc (<Esc> returns to normal mode)

A finally, appends face at the end of the line

user41805

Posted 2018-03-27T15:59:47.357

Reputation: 16 320

27 bytes: Try it online!

– James – 2018-03-27T19:40:58.853

13

Python, 144 bytes

def f(s):
 s=s[0].upper()+s[1:].lower()
 y=lambda s:s[:-1]if s[-1]=='y'else s
 t=y(s)
 u=s[:-2]if s[-2:]=='ey'else y(s)
 return t+'y Mc%sface'%u

Try it online here

touch my body

Posted 2018-03-27T15:59:47.357

Reputation: 231

2my first ever code golf attempt... – touch my body – 2018-03-27T16:44:25.050

3

welcome to PPCG! might I suggest adding a link to Try it Online! for verification of correctness?

– Giuseppe – 2018-03-27T16:46:02.183

1f("Face") does not comply with the current test cases (TIO). – Jonathan Frech – 2018-03-27T17:13:07.410

Edited post for correctness, also added a Try It Online! link – touch my body – 2018-03-27T17:30:25.840

136 bytes. – Jonathan Frech – 2018-03-27T18:26:38.907

126 bytes – caird coinheringaahing – 2018-03-27T18:31:46.043

105 bytes – PurkkaKoodari – 2018-03-27T18:54:10.433

197 bytes. – totallyhuman – 2018-03-27T19:04:26.930

12

Excel, 204 144 137 165 bytes

=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(REPT(REPLACE(LOWER(A1),1,1,UPPER(LEFT(A1)))&"~",2),"~","y Mc",1),"yy ","y "),"ey~","~"),"y~","~"),"~","face")

From the inside outwards:

REPLACE(LOWER(A1),1,1,UPPER(LEFT(A1)))      Replaces PROPER to handle space-delimited cases
REPT(%&"~",2)                   Duplicate.                    Donkey~Donkey~
SUBSTITUTE(%,"~","y Mc",1)      Replace first ~.              Donkeyy McDonkey~
SUBSTITUTE(%,"yy ","y ")        Handle words ending in 'y'.   Donkey McDonkey~
SUBSTITUTE(%,"ey~","~")         Handle words ending in 'ey'   Donkey McDonk~
SUBSTITUTE(%,"y~","~")          Handle words ending in 'y'    Donkey McDonk~
SUBSTITUTE(%,"~","face")        Adding face.                  Donkey McDonkface

Old answer, creating all bits separately, and then concatenating (176 bytes). Does not handle space-delimited cases correctly.

=PROPER(A1)&IF(LOWER(RIGHT(A1,1))="y",,"y")&" Mc"&IF(LOWER(RIGHT(A1,2))="ey",LEFT(PROPER(A1),LEN(A1)-2),IF(LOWER(RIGHT(A1,1))="y",LEFT(PROPER(A1),LEN(A1)-1),PROPER(A1)))&"face"

Wernisch

Posted 2018-03-27T15:59:47.357

Reputation: 2 534

Unfortunately, due to the requirement of handling space-delimited cases, PROPER(A1) is invalid (see the DJ Grand Master Flash input case), the best replacement that I could find while working on my VBA solution was LEFT(UPPER(A1))&MID(LOWER(A1),2,LEN(A1)) - please let me know if you end up golfing that down. – Taylor Scott – 2018-04-10T01:21:50.930

1Thank you @TaylorScott. Found 'REPLACE(LOWER(A1),1,1,UPPER(LEFT(A1)))` which is 2 bytes shorter. – Wernisch – 2018-04-12T09:26:49.017

11

Perl 6, 42 37 35 bytes

{S/y$//~"y Mc{S/e?y$//}face"}o&tclc

Try it online!

nwellnhof

Posted 2018-03-27T15:59:47.357

Reputation: 10 037

9

C# (.NET Core), 122 108 139 175 180 179 154 bytes

Thanks a lot, lee!

s=>((s.EndsWith("y")?s:s+"y")+" Mc"+(s+"$").Replace("ey$","")+"face").Replace(s,s.ToUpper()[0]+s.Substring(1).ToLower()).Replace("y$","").Replace("$","");

Try it online!

C# (.NET Core, with LINQ), 152 bytes

s=>((s.Last()=='y'?s:s+"y")+" Mc"+(s+"$").Replace("ey$","")+"face").Replace(s,s.ToUpper()[0]+s.Substring(1).ToLower()).Replace("y$","").Replace("$","");

Try it online!

Anderson Pimentel

Posted 2018-03-27T15:59:47.357

Reputation: 213

3Welcome to the site! :) – James – 2018-03-28T16:55:34.210

7

SOGL V0.12, 38 bytes

lW y≠F
u⁽³:F y*+pF‽j:lW e=⌡j}"‰θ`√►׀‘p

Try it Here!

dzaima

Posted 2018-03-27T15:59:47.357

Reputation: 19 048

7

Ruby, 61 49 bytes

->s{s.capitalize=~/(e)?y$|$/;"#$`#$1y Mc#$`face"}

Try it online!

Saved 12 sweet bytes thanks to @MartinEnder:

Reinstate Monica -- notmaynard

Posted 2018-03-27T15:59:47.357

Reputation: 1 053

1

Using the regex from my Retina answer and making a bit more use of string interpolation gets this down to 49: https://tio.run/##DcxBCsIwEEDRqwxJBF3Y4lpSN0U3igcQwTQmGFptMVNkTOLVY3bvb/577ihbmdeND77SanKoBvc18lcvzWpHIop6y7i4cbEhOOkiq7RhKS8@oRsVwr4ktOdDwdMNBEd1J2jHV28oVUbpB4SIEaYZPTAeMIFsgAd7wWsqmz8

– Martin Ender – 2018-03-28T13:42:43.610

@MartinEnder Wow, that is quite a difference. I don't think I've seen string interpolation without brackets. I'll take it if you don't want to use it for your own Ruby answer. – Reinstate Monica -- notmaynard – 2018-03-28T15:04:38.403

Nah, it's fine, I wouldn't have come up with using =~ and building the whole string instead of using sub. String interpolation can be used without brackets if the variable is a global, instance or class variable. – Martin Ender – 2018-03-28T15:05:39.627

7

Python 3, 80 bytes

Long time avid reader, my first submission at last !

lambda y:re.sub("([\w ]+?)((e)?y)?$",r"\1\3y Mc\1face",y.capitalize())
import re

Try it online

etene

Posted 2018-03-27T15:59:47.357

Reputation: 448

1Welcome to PPCG, and very nice first post! – Zacharý – 2018-03-30T14:38:14.087

6

Retina, 29 bytes

.+
$T
0`(e)?y$|$
$1y Mc$`face

Try it online!

Martin Ender

Posted 2018-03-27T15:59:47.357

Reputation: 184 808

5

Python 2, 88 92 bytes

lambda s:(s+'y'*-~-(s[-1]in'yY')).title()+' Mc'+re.sub('e?y$','',s.title())+'face'
import re

Try it online!

Chas Brown

Posted 2018-03-27T15:59:47.357

Reputation: 8 959

3Fails with 'FamilY' – Dead Possum – 2018-03-28T09:35:28.503

@Dead Possum: Fixed. Thks! – Chas Brown – 2018-03-28T18:04:03.277

5

Java 8, 121 112 107 106 bytes

s->(s=(char)(s.charAt(0)&95)+s.toLowerCase().substring(1)).split("y$")[0]+"y Mc"+s.split("e?y$")[0]+"face"

-1 byte thanks to @OliverGrégoire.

Explanation:

Try it online.

s->                         // Method with String as both parameter and return-type
  (s=                       //  Replace and return the input with:
     (char)(s.charAt(0)&95) //   The first character of the input as Uppercase
     +s.toLowerCase().substring(1))
                            //   + the rest as lowercase
  .split("y$")[0]           //  Remove single trailing "y" (if present)
  +"y Mc"                   //  Appended with "y Mc"
  +s.split("e?y$")[0]       //  Appended with the modified input, with "y" or "ey" removed
  +"face"                   //  Appended with "face"

Kevin Cruijssen

Posted 2018-03-27T15:59:47.357

Reputation: 67 575

What if the first char is not alphabetical? Or maybe we can get a rule added about that.. – streetster – 2018-03-28T13:14:26.297

1@streetster Just asked OP, and it seems the input will only contains uppercase and/or lowercase letters. – Kevin Cruijssen – 2018-03-28T13:20:26.553

1~32 -> 95 for 1 byte saved – Olivier Grégoire – 2018-03-29T09:38:16.763

@OlivierGrégoire I really need to start learning a bit more about bitwise operations.. >.> – Kevin Cruijssen – 2018-03-29T09:56:25.640

4

JavaScript, 103 96 94 bytes

Pretty naïve first pass at this.

s=>(g=r=>s[0].toUpperCase()+s.slice(1).toLowerCase().split(r)[0])(/y$/)+`y Mc${g(/e?y$/)}face`

Try it online

Shaggy

Posted 2018-03-27T15:59:47.357

Reputation: 24 623

s=>${s=s[0].toUpperCase()+s.slice(1).toLowerCase().replace(/y$/,``)}y Mc${s.replace(/e?y$/,``)}face – Benjamin Gruenbaum – 2018-03-27T18:44:50.177

One less: s=>${s=s[0].toUpperCase()+s.slice(1).toLowerCase().replace(/y$/,'')}y Mc${s.replace(/e$/,``)}face – Benjamin Gruenbaum – 2018-03-27T18:50:30.907

Thanks, @BenjaminGruenbaum, but the first fails for Donkey and the second for Face. – Shaggy – 2018-03-27T19:04:08.327

The markdown is ruining the code: https://gist.github.com/benjamingr/8fec077b5436846cc9c52be353238037

– Benjamin Gruenbaum – 2018-03-27T19:05:45.290

@Shaggy i managed to reduce the g function by some chars :). you can look in my solution – DanielIndie – 2018-03-28T16:55:55.330

3

Perl 5 -p, 47 39 bytes

Saved 6 bytes with @OlegV.Volkov's suggestions, 1 with @mwellnhof's, and 1 on my own

$_=lc^$";$_=s/y?$/y Mc/r.s/e?y$//r.face

Try it online!

Xcali

Posted 2018-03-27T15:59:47.357

Reputation: 7 671

You can get rid of ucfirst: $_=lc^$"; – Oleg V. Volkov – 2018-03-28T14:39:13.997

$_=s/y$//r."y Mc".s/e?y$//r.face is one byte shorter. – nwellnhof – 2018-03-28T14:55:56.990

1/y$|$/ -> /y?$/ – Oleg V. Volkov – 2018-03-28T20:34:09.780

Duh. I should have realized that. – Xcali – 2018-03-29T02:53:14.797

3

vim, 35 34 bytes

Vu~Yp:s/ey$
:%s/y$
kgJiy Mc<ESC>Aface<ESC>

<ESC> is 0x1b

Ungolfed

Vu~                      # Caseify McCaseface
Yp                       # dup line
:s/ey$ 
:%s/y$                   # Get the suffixes right
kgJiy Mc<ESC>Aface<ESC>  # Join lines and add the extra chars

Try it online!

Saved 1 byte thanks to DJMcMayhem

Ray

Posted 2018-03-27T15:59:47.357

Reputation: 1 488

1You can do Y instead of yy – James – 2018-03-28T04:06:39.727

3

C++ 14 (g++), 181 171 148 147 134 bytes

[](auto s){s[0]&=95;int i=1,b;for(;s[i];)s[i++]|=32;b=s[--i]-'y';return s+(b?"y":"")+" Mc"+(b?s:s.substr(0,s[i-1]-'e'?i:i-1))+"face";}

Note that clang will not compile this.

Credit goes to Kevin Cruijssen and Olivier Grégoire for the &95 trick.

Thanks to Chris for golfing 11 bytes.

Try it online here.

Ungolfed version:

[] (auto s) { // lambda taking an std::string as argument and returning an std::string
    s[0] &= 95; // convert the first character to upper case
    int 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
    // i is now s.length()
    b = s[--i] - 'y'; // whether the last character is not a 'y'
    // i is now s.length()-1
    return s + (b ? "y" : "") // append 'y' if not already present
    + " Mc"
    + (b ? s : s.substr(0, s[i-1] - 'e' ? i : i-1)) // remove one, two, or zero chars from the end depending on b and whether the second to last character is 'e'
    + "face";
}

O.O.Balance

Posted 2018-03-27T15:59:47.357

Reputation: 1 499

I don't know C++ that well, but you can golf 9 bytes: Try it online 172 bytes. Summary of changes: s[0]=s[0]&~32; to s[0]&=~32;; s[i++]=s[i]|32; to s[i++]|=32; and int i=1,n=s.length()-1,b; so you only need 1 int.

– Kevin Cruijssen – 2018-03-28T14:05:45.777

Oh, and one more byte by removing the space at #include<string> – Kevin Cruijssen – 2018-03-28T14:06:33.507

@KevinCruijssen thanks for catching that! I have edited. – O.O.Balance – 2018-03-28T14:19:32.260

You can save 11 bytes by not defining n and just using the value of i after the while loop. Try it online!

– Chris – 2018-03-30T18:34:12.223

@Chris Thanks! I managed to shave off 2 more bytes. – O.O.Balance – 2018-03-30T23:19:18.323

129 bytes – ceilingcat – 2019-07-31T04:57:30.933

2

Elixir, 112 110 107 106 bytes

now as short as java

fn x->x=String.capitalize x;"#{x<>if x=~~r/y$/,do: "",else: "y"} Mc#{String.replace x,~r/e?y$/,""}face"end

Try it online!

Explanation:

x=String.capitalize x

Gets x with the first character in uppercase and all others lowercase.

#{ code }

Evaluate the code and insert it into the string.

#{x<>if x=~ ~r/y$/, do: "", else: "y"}

Concatenates x with y if it does not end with y (ie it does not match the regex y$).

#{String.replace x, ~r/e?y$/, "")}

Removes trailing ey and trailing y.

Okx

Posted 2018-03-27T15:59:47.357

Reputation: 15 025

2

V, 38 36 32 bytes

-5 byte thanks to @Cows quack

Vu~hy$ó[^y]$/&y
A Mc<esc>póe¿y$
Aface

<esc> is a literal escape character and [^ is encoded as \x84

Try it online!

Herman L

Posted 2018-03-27T15:59:47.357

Reputation: 3 611

gu$ can become Vu – user41805 – 2018-03-27T18:23:43.480

2

Since [^ is a regex shortcut (see here), you can use 0x84 instead of [^ to save a byte. Similarly, \? can be simplified into <M-?> to save another byte. And $a => A

– user41805 – 2018-03-27T18:37:07.190

2

Ruby, 69 bytes

->s{"#{(s.capitalize!||s)[-1]==?y?s:s+?y} Mc#{s.gsub /e?y$/,""}face"}

Explanation:

->s{                                                                } # lambda 
    "#{                                 } Mc#{                }face" # string interpolation
       (s.capitalize!||s) # returns string capitalized or nil, in that case just use the original string
                         [-1]==?y # if the last character == character literal for y
                                 ?s:s+?y # then s, else s + "y"
                                              s.gsub /e?y$/,"" # global substitute
                                                               # remove "ey" from end

Try it online!

dkudriavtsev

Posted 2018-03-27T15:59:47.357

Reputation: 5 781

Could you add a TIO link? I don't know Ruby, but does s.capitalize replace the previous s? If not, does /e?y$/ handle a test case ending in Y, EY, or Ey correctly? – Kevin Cruijssen – 2018-03-28T13:57:28.170

1@KevinCruijssen s.capitalize vs s.capitalize! (different functions). s.capitalize! clobbers the old version. – dkudriavtsev – 2018-03-28T19:32:50.927

@KevinCruijssen I've added a TIO link. – dkudriavtsev – 2018-03-28T19:35:02.937

@KevinCruijssen Also added an explanation – dkudriavtsev – 2018-03-28T19:41:16.883

Ah ok, thanks for the explanation and the information about s.capitalize!. Never programmed in Ruby, but adding an explanation mark to replace the previous value is pretty cool. +1 from me. – Kevin Cruijssen – 2018-03-29T08:14:37.913

2

Python 3, 117 114 bytes

-3 bytes thanks to Dead Possum

def f(s):s=s.title();return s+'y'*(s[-1]!='y')+' Mc'+([s,s[:-1],0,s[:-2]][(s[-1]=='y')+((s[-2:]=='ey')*2)])+'face'

Try it online!

Dat

Posted 2018-03-27T15:59:47.357

Reputation: 879

3rd element of list [s,s[:-1],'',s[:-2] can be changed to 0 to save 1 byte. – Dead Possum – 2018-03-28T09:34:18.710

In 'y'*1 *1 is not needed. 2 more bytes – Dead Possum – 2018-03-28T09:34:42.697

Switching from Python 3 to Python 2, and replacing return with print is 1 byte shorter. – Kevin Cruijssen – 2018-03-28T12:57:25.730

2

K4, 74 69 68 bytes

Solution:

{$[r;x;x,"y"]," Mc",_[r:0&1-2/:"ye"=2#|x;x:@[_x;0;.q.upper]],"face"}

Examples:

q)k)f:{$[r;x;x,"y"]," Mc",_[r:0&1-2/:"ye"=2#|x;x:@[_x;0;.q.upper]],"face"}
q)f each ("boat";"Face";"DOG";"Family";"Lady";"Donkey";"Player")
"Boaty McBoatface"
"Facey McFaceface"
"Dogy McDogface"
"Family McFamilface"
"Lady McLadface"
"Donkey McDonkface"
"Playery McPlayerface"

Explanation:

Figure out if the last characters are equal to "ey", convert result to base-2 so we can ignore words that end "e?". Index into a list of numbers of characters to trim.

Managed to shave 5 bytes off my code to determine whether the last two chars at "ey" but struggling to better it...

{$[r;x;x,"y"]," Mc",_[r:0&1-2/:"ye"=2#|x;x:@[_x;0;.q.upper]],"face"} / the solution
{                                                                  } / lambda function
                                                            ,"face"  / join with "face"
                    _[                  ;                  ]         / cut function
                                           @[_x; ;        ]          / apply (@) to lowercased input
                                                0                    / at index 0
                                                  .q.upper           / uppercase function
                                         x:                          / save back into x
                                      |x                             / reverse x
                                    2#                               / take first two chars of x
                               "ye"=                                 / equal to "ye"?
                             2/:                                     / convert to base 2
                           1-                                        / subtract from 1
                         0&                                          / and with 0 (take min)
                       r:                                            / save as r
             ," Mc",                                                 / join with " Mc"
 $[r;x;x,"y"]                                                        / join with x (add "y" if required)

Bonus:

67 byte port in K (oK):

{$[r;x;x,"y"]," Mc",((r:0&1-2/"ye"=2#|x)_x:@[_x;0;`c$-32+]),"face"}

Try it online!

streetster

Posted 2018-03-27T15:59:47.357

Reputation: 3 635

1What's the point in the K4 if your oK port defeats it? – Zacharý – 2018-03-27T21:33:48.233

I didn't think it would, and the port doesn't work if the first char isn't alphabetical as I blindly subtract 32 from the ASCII value - there's no "upper" built-in. – streetster – 2018-03-28T13:11:32.157

2

Red, 143 142 bytes

func[s][s: lowercase s s/1: uppercase s/1
w: copy s if"y"<> last s[append w"y"]rejoin[w" Mc"parse s[collect keep to[opt["y"|"ey"]end]]"face"]]

Try it online!

Ungolfed:

f: func[s][
   s: lowercase s                      ; make the entire string lowercase
   s/1: uppercase s/1                  ; raise only its first symbol to uppercase 
   w: copy s                           ; save a copy of it to w
   if "y" <> last s[append w "y"]     ; append 'y' to w if it doesn't have one at its end
   rejoin[w                            ; assemble the result by joining:
          " Mc"
          ; keep the string until "y", "ey" or its end
          parse s[collect keep to [opt ["y" | "ey"] end]]
          "face"
    ]
]

Galen Ivanov

Posted 2018-03-27T15:59:47.357

Reputation: 13 815

2

05AB1E, 30 bytes

™D'y©Ü®«s¤®Qi¨¤'eQi¨]’McÿŠÑ’ðý

Try it online! or as a Test suite

Emigna

Posted 2018-03-27T15:59:47.357

Reputation: 50 798

2

JavaScript (Node.js), 87 bytes

  • thanks to @Shaggy for 5 reducing 5 bytes
s=>(g=r=>Buffer(s.replace(r,"")).map((x,i)=>i?x|32:x&~32))(/y$/)+`y Mc${g(/e?y$/)}face`

Try it online!

DanielIndie

Posted 2018-03-27T15:59:47.357

Reputation: 1 220

2You don't have to name non-recursive functions. – Dennis – 2018-03-28T17:01:15.363

1

Nicely done. I never think to use Buffer, will have to try to remember it for future challenges. Got it down to 87 bytes for you.

– Shaggy – 2018-03-28T17:25:12.860

2

Jstx, 27 bytes

h</►yT↓►y/◙♂ Mc♀/◄eyg►yg/íå

Explanation

      # Command line args are automatically loaded onto the stack
h     # Title case the top of the stack
<     # Duplicate the top value on the stack twice
/     # Print the top value on the stack
►y    # Load 'y' onto the stack
T     # Returns true if the 2nd element on the stack ends with the top
↓     # Execute block if the top of the stack is false
  ►y  # Load 'y' onto the stack
  /   # Print the top value on the stack
◙     # End the conditional block
♂ Mc♀ # Load ' Mc' onto the stack
/     # Print the top value on the stack
◄ey   # Load 'ey' onto the stack
g     # Delete the top of the stack from the end of the 2nd element on the stack if it exists
►y    # Load 'y' onto the stack
g     # Delete the top of the stack from the end of the 2nd element on the stack if it exists
/     # Print the top of the stack
íå    # Load 'face' onto the stack
      # Print with newline is implied as the program exits

Try it online!

Quantum64

Posted 2018-03-27T15:59:47.357

Reputation: 371

I haven't seen this language before. It looks interesting. Is there documentation? – recursive – 2018-03-31T22:29:57.977

1

@recursive Here's some documentation.

– Quantum64 – 2018-04-01T04:44:26.227

Wow, this is really impressive. Especially for so little development time. I'm excited to see where this goes. – recursive – 2018-04-01T05:08:32.660

2

PHP: 132

<?php function f($s){$s=ucfirst(strtolower($s));return $s.(substr($s,-1)=='y'?'':'y').' Mc'.preg_replace('/(ey|y)$/','',$s).'face';}

Explanation:

<?php

function f($s)
{
    // Take the string, make it all lowercase, then make the first character uppercase
    $s = ucfirst(strtolower($s));

    // Return the string, followed by a 'y' if not already at the end, then ' Mc'
    // and the string again (this time, removing 'y' or 'ey' at the end), then
    // finally tacking on 'face'.
    return $s
        . (substr($s, -1) == 'y' ? '' : 'y')
        . ' Mc'
        . preg_replace('/(ey|y)$/', '', $s)
        . 'face';
}

Chris Forrence

Posted 2018-03-27T15:59:47.357

Reputation: 141

2

Pyth, 36 34 bytes

++Jrz4*\yqJK:J"e?y$"k+" Mc"+K"face

Try it online!

Explanation:

++Jrz4*\yqJK:J"(e)?y$"k+" Mc"+K"face

  Jrz4                                  Set J to the titlecase of z (input)
           K:J"e?y$"k                   Set K to (replace all matches of the regex e?y$ in J with k (empty string))
         qJ                             Compare if equal to J
      *\y                               Multiply by "y" (if True, aka if no matches, this gives "y", else it gives "")
 +                                      Concatenate (with J)
                             +K"face    Concatenate K with "face"
                       +" Mc"           Concatenate " Mc" with that
+                                       Concatenate

RK.

Posted 2018-03-27T15:59:47.357

Reputation: 497

Sadly this doesn't work, as the last test case fails. – Zacharý – 2018-03-30T16:16:54.853

Switch rz3 to rz4 to get this to work properly for the last test case. – hakr14 – 2018-03-30T18:10:18.373

Oh whoops, I'll fix that :P – RK. – 2018-03-30T22:50:49.753

2

Jelly, 77 75 74 73 bytes

2ḶNṫ@€⁼"“y“ey”S
ØA;"ØaF
¢y⁸µ¢Uyµ1¦
Çṫ0n”yẋ@”y;@Ç;“ Mc”
⁸JU>ÑTị3Ŀ;@Ç;“face

Try it online!

Any golfing suggestions are welcome (and wanted)!

Zacharý

Posted 2018-03-27T15:59:47.357

Reputation: 5 710

1

Python, 105 104

import re;r=re.sub;c=str.capitalize;f=lambda s:r('([^e^y])$','\\1y',c(s))+' Mc'+r('ey$','',c(s))+'face'

thx @Berry M. from noticing my dyslexia

dieter

Posted 2018-03-27T15:59:47.357

Reputation: 2 010

3-1 byte if you spell Mc correctly! – Berry M. – 2018-03-29T09:45:24.230

1

Pyth, 60 59 bytesSBCS

K"ey"Jrz4Iq>2JK=<2J=kK.?=k\yIqeJk=<1J))%." s÷   WZÞàQ"[JkJ

Test suite

They don't display here, but three bytes, \x9c, \x82, and \x8c are in the packed string between s and ÷. Rest assured, the link includes them.

Python 3 translation:
K="ey"
J=input().capitalize()
if J[-2:]==K:
    J=J[:-2]
    k=K
else:
    k="y"
    if J[-1]==k:
        J=J[:-1]
print("{}{} Mc{}face".format(J,k,J))

hakr14

Posted 2018-03-27T15:59:47.357

Reputation: 1 295

1

APL (Dyalog Classic), 95 90 88 87 86 85 84 82 80 78 77 73 bytes

{'face',⍨(' Mc',S↓⍨-+/∧/¨Y'ey'=¨↑∘S¨-⍳2),⍨S,(Y≠⊃⌽S←⍵(819⌶¨)⍨1=⍳⍴⍵)/Y←'y'}

Try it online!

This could be golfed down some more, and any suggestions are welcome!

Zacharý

Posted 2018-03-27T15:59:47.357

Reputation: 5 710

1

PHP, 45 46 bytes

<?=($s=ucfirst(fgets(STDIN)))."y Mc{$s}face";

Try it online!

Berry M.

Posted 2018-03-27T15:59:47.357

Reputation: 121

Fails in two different ways with input boAty. (Wrong caps, 'y' not removed). – Oleg V. Volkov – 2018-03-29T13:50:29.490

1

Clojure: 161 155

(use '[clojure.string :as s])
(defn f[t](s/join[(s/capitalize(cond(=(last t)\y)t :else(s/join[t "y"])))" Mc"(s/capitalize(s/replace t #"e*y$" ""))"face"]))

Ungolfed:

(defn facegen [s0]
  (let [ s1 (clojure.string/capitalize (cond
                                         (= (last s0) \y)  s0
                                         :else             (clojure.string/join [s0 "y"])))
         s2 (clojure.string/capitalize (clojure.string/replace s0 #"e*y$" ""))]
    (clojure.string/join [s1 " Mc" s2 "face"])))

Try it online!

Bob Jarvis - Reinstate Monica

Posted 2018-03-27T15:59:47.357

Reputation: 544

1

APL (Dyalog Classic), 62 bytes

{'face',⍨(' Mc','e?y$'⎕r''⊢S),⍨S,(Y≠⊃⌽S←⍵(819⌶¨)⍨1=⍳⍴⍵)/Y←'y'}

Try it online!

Thanks to @ngn for this solution!

Zacharý

Posted 2018-03-27T15:59:47.357

Reputation: 5 710

1

Unix (79 bytes)

Using Standard input :

 rev|sed -r 's/(.*)(.)$/\L\1\U\2/;s/^(ye?)?(.*)$/ecaF\2cM y\1\2/;s/ yy/ y/'|rev

test :

echo -e "Lady\nFace\nDonkey\nyyy"|rev|sed -r 's/(.*)(.)$/\L\1\U\2/;s/^(ye?)?(.*)$/ecaF\2cM y\1\2/;s/ yy/ y/'|rev
Lady McLadFace
Facey McFaceFace
Donkey McDonkFace
Yyy McYyFace

or ( by Function) :

F(){ echo $1|rev|sed -r 's/(.*)(.)$/\L\1\U\2/;s/^(ye?)?(.*)$/ecaF\2cM y\1\2/;s/ yy/ y/'|rev;}

test :

 F donkey
 Donkey McDonkFace

Ali ISSA

Posted 2018-03-27T15:59:47.357

Reputation: 211

1

PowerShell Core, 98 bytes

(("y$","e?(?=y)y$"|%{$o.ToUpper()[0]+$o.ToLower().Substring(1)-replace $_,""})-join "y Mc")+"face"

Try it online!

Many thanks to @Anderson Pimentel for inspiring a solution using regex replacements!

Jeff Freeman

Posted 2018-03-27T15:59:47.357

Reputation: 221

1

Excel VBA, 134 bytes

An anonymous VBE Immediate Window Function that takes input from range [A1] and outputs to the Immediate Window.

b=[Left(Upper(A1))]+Mid([Lower(A1)],2):l=len(b):y=[Right(A1)="y"]:?b;IIf(y,"","y")" Mc"IIf(y,Left(b,l-1+(InStrRev(b,"e")=l-1)),b)"face

Taylor Scott

Posted 2018-03-27T15:59:47.357

Reputation: 6 709