Given an email address, the result of a transformation applied to that email address, and a second email address, return the output of the same transformation applied to the second email address.

The email addresses will all have the following structure:

A string of positive length containing alphanumeric characters and at most one . (the local part), followed by an @ symbol, followed by a string of positive length containing alphanumeric sumbols (the domain), followed by a . symbol, and a final string of positive length containing alphanumeric characters (the TLD).

There are four allowed transformations:

• Identity (no change). (a.b@c.d -> a.b@c.d)
• Returning just the local part (everything before the @) unmodified (a.b@c.d -> a.b).
• Returning the local part split on the . if present, with the first symbol of each half capitalised. (a.b@c.d -> A B).
• Returning just the domain (everything between the @ and the final .) unmodified. (a.b@c.d -> c).

When more than one transformation is possible, you can give the output of any of the possibilities. Whitespace at the start and end of output don't matter, but in the middle does (i.e. if you split a.b to A B there should be just one space in the middle [and any number at the start and end of output], but if you split a., then A with any number of spaces on either side are all acceptable).

Examples (input | output):

john.doe@gmail.com, John Doe, phillip.maini@gmail.com         | Phillip Maini
John.Doe@gmail.com, John Doe, Phillip.Maini@gmail.com         | Phillip Maini
foo.bar@hotmail.com, foo.bar, gee.whizz@outlook.com           | gee.whizz
foo.bar@hotmail.com, foo.bar, gEe.Whizz@outlook.com           | gEe.Whizz
rodney.dangerfield@comedy.net, comedy, michael.scott@office.0 | office
.jones@x.1, Jones, a.@3.z                                     | A
.jones@x.1, .jones@x.1, a.@3.z                                | a.@3.z
.jones@x.1, .jones, a.@3.z                                    | a.
.jones@x.1, x, a.@3.z                                         | 3
.@b.c, .@b.c, 1@2.3                                           | 1@2.3
john.jones@f.f, John Jones, 1in.thehand@2inthe.bush           | 1in Thehand
chicken.soup@q.z, Chicken Soup, fab@ulou.s                    | Fab
lange@haare.0, lange, fat.so@fat.net                          | fat.so
Lange@haare.0, Lange, fat.so@fat.net                          | {fat.so, Fat So} # either acceptable
chicken@chicken.chicken, chicken, horse@pig.farm              | {horse, pig} # either acceptable


Usual rules and loopholes apply.

• Shouldn't the last test case return "horse"? I don't see why it can return "pig" instead. – Erik the Outgolfer Oct 30 '17 at 16:25
• @EriktheOutgolfer because the 4th transformation is to return just the domain (the part between @ and final .). Since the local part and domain are both chicken, it's ambiguous whether it's the 2nd or 4th transformation – LangeHaare Oct 30 '17 at 16:28
• Oh, I misinterpreted that. – Erik the Outgolfer Oct 30 '17 at 16:30
• May we require that the relevant input is formatted with the space in all cases (e.g. in the test where the output is A [with a trailing space] that the second input be Jones [with a leading space])? – Jonathan Allan Oct 30 '17 at 21:08
• I don't understand why .jones@x.1, Jones, a.@3.z is A - if jones is matched that means the matching part is the part between the first period and the @ symbol. But that would result in an empty string because the a is before the first period and not after. – Jerry Jeremiah Oct 31 '17 at 0:17

# Java 8, 254240 236 bytes

(a,b,c)->{String A[]=a.split("@"),C[]=c.split("@"),x="";for(String p:C[0].split("\\."))x+=(p.charAt(0)+"").toUpperCase()+p.substring(1)+" ";return a.equals(b)?c:A[0].equals(b)?C[0]:A[1].split("\\.")[0].equals(b)?C[1].split("\\.")[0]:x;}


-4 bytes thanks to @LukeStevens.

Explanation:

Try it here.

(a,b,c)->{                  // Method with three String parameters and String return-type
String A[]=a.split("@"),  //  Split a by "@" into two parts
C[]=c.split("@"),  //  Split c by "@" into two parts
x="";              //  Temp-String
for(String p:C[0].split("\\."))
//  Loop over the first part of c, split by dots
x+=                     //   Append String x with:
(p.charAt(0)+"").toUpperCase()
//    The first character as uppercase
+p.substring(1)      //    + the rest of the String
+" ";                //    + a space
//  End of loop (implicit / single-line body)
return a.equals(b)?       //  If input a and b are exactly the same:
c                       //   Return c
:A[0].equals(b)?         //  Else-if the first part of a equals b:
C[0]                    //   Return the first part of c
:A[1].split("\\.)[0].equals(b)?
//  Else-if the domain of a equals b
C[1].split("\\.)[0]     //   Return the domain of c
:                        //  Else:
x;                      //   Return String x
}                           // End of method

• You can knock off 4 bytes by using (p.charAt(0)+"").toUpperCase() instead of Character.toUpperCase(p.charAt(0)). – Luke Stevens Oct 31 '17 at 10:17
• @LukeStevens Thanks! I had (char)(p.charAt(0)&~32) at first, but this didn't work due to the 1in Thehand test case. But uppercasing it as String is indeed shorter than Character.toUpperCase, so thanks! – Kevin Cruijssen Oct 31 '17 at 11:18

import Data.Char
s c""=[]
s c a=w:f t where
(w,t)=span(/=c)a
f(_:y)=s c y
f _=[]
u""=""
u(x:y)=toUpper x:y
l=h.s '@'
f x y=h[t|t<-[id,l,unwords.filter(/="").map u.s '.'.l,h.s '.'.last.s '@'],t x==y]


Try it online!

It is sad I had to spend 59 bytes on reinventing split (s).

The solution creates a list of transformations and returns the first one that leads to the expected result.

• Welcome to the site! I don;t know Haskell, but is it possible to remove any of the whitespace characters, such as newlines and spaces? – caird coinheringaahing Oct 31 '17 at 14:36
• Nice first answer! You might be interested in our collection of tips for golfing in Haskell, especially this and this should save some bytes. – Laikoni Oct 31 '17 at 21:25
• Also feel free to join us in Of Monads and Men, a chat room for golfing and general discussion of Haskell. – Laikoni Oct 31 '17 at 21:27

# Jelly, 40 bytes

Pre-emptive thanks to Erik the Outgolfer for noticing the failure of using Œt (title-case) and hence Œu1¦€K over ŒtK

-1 byte thanks to Erik the Outgolfer (rearrangement of ⁵⁸ç⁹¤Ŀ to çµ⁵⁸Ŀ)


ÑṪṣ”.Ḣ
ṣ”@
ÇḢ
Çṣ”.Œu1¦€K
⁹ĿðÐ€5i
çµ⁵⁸Ŀ


A full program taking exampleEmail, exampleOutput, realEmail and printing the result.

Try it online!

### How?

Performs all four transforms (plus a precursor one), finds the first one that yields the example from the first email, then applies it to the second email:

            - Link 1, do nothing: email
- do nothing but return the input

ÑṪṣ”.Ḣ      - Link 2, the domain: email
Ñ           - call the next link (3) as a monad (split at "@")
Ṫ          - tail
ṣ”.       - split at "."

ṣ”@         - Link 3, split at @: email
ṣ”@         - split at "@"

ÇḢ          - Link 4, local part: email
Ç           - call the last link (3) as a monad (split at "@")

Çṣ”.Œu1¦€K  - Link 5, name-ified: email
Ç           - call the last link (4) as a monad (get the local part)
ṣ”.        - split at "."
¦€   - for €ach sparsley apply:
1     - ...to index: 1
Œu      - ...action: uppercase
K  - join with space(s)

Ð€5      - map across (implicit range of) 5 (i.e. for each n in [1,2,3,4,5]):
ð         -   dyadicly (i.e. with n on the right and exampleEmail on the left):
⁹           -     ...reference: chain's right argument, n
i     - first index of exampleOutput in the resulting list

çµ⁵⁸Ŀ       - Main link: exampleEmail; exampleOutput
µ          - monadic chain separation (call that L)
⁸        - chain's left argument, L
Ŀ       - call the link at that reference as a monad with input:
⁵         -   program's third input, realEmail


Notes:

1. Assumes the input exampleOutput is strictly the same as the output would be.

2. The "precursor" (the result of link 3) is tested for matching the exampleOutput, but it won't match unless the exampleOutput itself is a list of lists of characters. As such the inputs should probably be quoted (Python formatting may be used here) to avoid the possibility of interpreting it as such.

# Python 2, 135 bytes

s,r,x=input()
def f(x):S,D=x.split('@');return x,S,' '.join(map(str.capitalize,S.split('.'))),D.split('.')[0]
print f(x)[f(s).index(r)]


Try it online!

• -3 bytes by moving strip – ovs Oct 30 '17 at 21:31
• @ovs thanks, anyways rules changed to remove the need for it – Erik the Outgolfer Oct 31 '17 at 12:43

# JavaScript (ES6), 145 bytes

Invoke with currying syntax, e.g. f('chicken.soup@q.z')('Chicken Soup')('fab@ulou.s')

x=>y=>[x=>x,s=x=>x.split@[0],x=>s(x).split..map(w=>w&&w[0].toUpperCase()+w.slice(1)).join .trim(),x=>/@(.+)\./.exec(x)[1]].find(f=>f(x)==y)


f=x=>y=>[x=>x,s=x=>x.split@[0],x=>s(x).split..map(w=>w&&w[0].toUpperCase()+w.slice(1)).join .trim(),x=>/@(.+)\./.exec(x)[1]].find(f=>f(x)==y)

for(const [x, y, z] of [
['john.doe@gmail.com', 'John Doe', 'phillip.maini@gmail.com'], // Phillip Maini
['John.Doe@gmail.com', 'John Doe', 'Phillip.Maini@gmail.com'], // Phillip Maini
['foo.bar@hotmail.com', 'foo.bar', 'gee.whizz@outlook.com'], // gee.whizz
['foo.bar@hotmail.com', 'foo.bar', 'gEe.Whizz@outlook.com'], // gEe.Whizz
['rodney.dangerfield@comedy.net', 'comedy', 'michael.scott@office.0'], // office
['.jones@x.1', 'Jones', 'a.@3.z'], // A
['.jones@x.1', '.jones@x.1', 'a.@3.z'], // a.@3.z
['.jones@x.1', '.jones', 'a.@3.z'], // a.
['.jones@x.1', 'x', 'a.@3.z'], // 3
['.@b.c', '.@b.c', '1@2.3'], // 1@2.3
['john.jones@f.f', 'John Jones', '1in.thehand@2inthe.bush'], // 1in Thehand
['chicken.soup@q.z', 'Chicken Soup', 'fab@ulou.s'], // Fab
['lange@haare.0', 'lange', 'fat.so@fat.net'], // fat.so
['Lange@haare.0', 'Lange', 'fat.so@fat.net'], // {fat.so, Fat So} # either acceptable
['chicken@chicken.chicken', 'chicken', 'horse@pig.farm'], // {horse, pig} # either acceptable
]) console.log( f(x)(y)(z) )

# Mathematica, 217 bytes

(L=Capitalize;T@x_:=(M=StringSplit)[x,"@"];P@x_:=#&@@T[x];W@x_:=If[StringContainsQ[P@x,"."],StringRiffle@L@M[P@x,"."],L@P@x];Z@x_:=#&@@M[T[x][[2]],"."];If[#==#2,#3,If[#2==P@#,P@#3,If[#2==W@#,W@#3,If[#2==Z@#,Z@#3]]]])&


->a,b,c{r=[/.*/,/(?<=@)\w*/,/[^@]*/].find{|x|r=c[x];a[x]==b}?r:r.sub(?.," ").gsub(/\b(.)/){$1.upcase}}  Try it online! # CJam, 42 q~@{[_\'@/~'./0=\_'.%{(eu\+}%S*]}:T~@a#\T=  Try it online Explanation: q~ read and evaluate the input (given as 3 quoted strings) @ bring the first string to the top of the stack {…}:T define a function T that calculates the 4 transformations of a string: [ begin array _\ duplicate the string, and swap with the other copy to bring it in the array (1st transformation) '@/~ split by '@' and put the 2 pieces on the stack './0= split the 2nd piece by '.' and keep the first part (4th transformation) \_ swap with the piece before '@' and duplicate it (2nd transformation) '.% split by '.', removing the empty pieces {…}% transform the array of pieces (eu take out the first character and capitalize it \+ prepend it back to the rest S* join the pieces by space (3rd transformation) ] end array ~ execute the function on the first string @a bring the 2nd string to the top of the stack, and wrap it in an array # find the position of this string in the array of transformations \T bring the 3rd string to the top and call function T = get the transformation from the array, at the position we found before  # PHP 7.1, 176 bytes <?$e=explode;[,$p,$q,$r]=$argv;echo$p==$q?$r:($e('@',$p)[0]==$q?$e('@',$r)[0]:($e('.',$e('@',$p)[1])[0]==$q?$e('.',$e('@',$r)[1])[0]:ucwords(join(' ',$e('.',$e('@',$r)[0])))));


Try it online!

# PHP < 7.1, 180 bytes

Versions under 7.1 would need to change the [,$p,$q,$r]=$argv to list(,$p,$q,$r)=$argv, adding 4 bytes.

## GNU sed, 105 + 1(r flag) = 106 bytes

The first three s commands check for the identity, local part and domain transformations respectively. If one transformation matches, then it is applied to the second email address and the following s commands will fail due to a lack of the input format.

s:^(.*),\1,::
s:(.*)@.*,\1,(.*)@.*:\2:
s:.*@(.*)\..*,\1,.*@(.*)\..*:\2:
s:.*,([^.]*)\.?(.*)@.*:\u\1 \u\2:


Try it online!

The local part split transformation (last s command) is the most expensive to check, in terms of bytes, therefore I placed it at the end and assumed it matches (since the other ones failed by that time), going directly to its application.

# Jelly, 43 bytes

ḢŒlṣ”.Œu1¦€K
ṣ”@Wẋ4j”@$ḷ/ÇṪṣ”.Ḣ$\$4ƭ€
Çiị⁵Ç¤


Try it online!

• Would ŒtK work in place of Œu1¦€K to save 3? – Jonathan Allan Oct 30 '17 at 21:12
• ...and what's the need for Œl? – Jonathan Allan Oct 30 '17 at 21:17
• ^ ah I see that 1in.thehand would not work with ŒtK. – Jonathan Allan Oct 30 '17 at 21:24
• @JonathanAllan Yep, that's the reason why I didn't use that, and also the reason ovs's (now deleted) answer was invalid (str.title). – Erik the Outgolfer Oct 31 '17 at 12:26