Write a function or program that, when given a list of names, outputs or returns a list where duplicates of given names have a unique shortened version of their surname.


A list of names, where a name is defined by a given name and a last name separated by a space. Names are non-empty strings containing only uppercase and lowercase letters. The list can be an array of strings, or the names separated by a constant non-alpha, non-space character, but the output must be in the same format as the input.


A list of the inputted names in the same order and format as the input that have been modified by these rules:

  • For unique given names, output just the given name
  • For names that share the same given name:
    • As well as their given name, add the shortest unique version of their surname that that is not shared by another name, followed by a period. For instance: John Clancy, John Smith becomes John C.,John S. and James Brown, James Bratte becomes James Bro.,James Bra.
    • If one surname is a subset of another, such as Julian King,Julian Kingsley, return the full surname of the smaller one without a period. The example would become Julian King,Julian King.
  • Basically a period represents the regex .+, where only one name should match it.
  • You may assume that no-one will share both the same given name and the same surname
  • Names are case-sensitive

Test Cases:

  • John Clancy,Julie Walker,John Walker,Julie Clancy -> John C.,Julie W.,John W.,Julie C.
  • Julian King,Jack Johnson,Julian Kingsley > Julian King,Jack,Julian King.
  • Jack Brown,Jack Black,Jack Blue > Jack Br.,Jack Bla.,Jack Blu.
  • John Storm,Jon Snow,Johnny Storm > John,Jon,Johnny
  • Jill DeSoma,Jill Desmond > Jill DeS.,Jill Des.

This is , so the lowest byte count for each language wins.

  • \$\begingroup\$ Related, related (Thanks @Laikoni). Sandbox Post \$\endgroup\$
    – Jo King
    Commented Jan 20, 2018 at 13:08
  • 1
    \$\begingroup\$ Where does the Angela C. come from the in the test case? \$\endgroup\$ Commented Jan 20, 2018 at 13:16
  • \$\begingroup\$ Meant to be a Julie oops, thanks. Fixed \$\endgroup\$
    – Jo King
    Commented Jan 20, 2018 at 13:25

3 Answers 3


Jelly,  34 33 32  30 bytes


A monadic link taking a list of lists of characters (i.e. a list of "strings") and returning the abbreviations in the same format and relative order.

Try it online! (a full program test suite)


;\ċÐf⁶t€⁶;€JṖḊ$$¦”.µ€ċ@ÐṂ€Ẏ$Ḣ€ - Link: list of lists    e.g. ["Sam Ng","Sam Li","Sue Ng"]
                   µ€          - monadically for €ach:  e.g. "Sue Ng"
 \                             -   cumulative reduce with:
;                              -     concatenation           ["S","Su","Sue","Sue ","Sue N","Sue Ng"]
     ⁶                         -   literal space character   ' '
   Ðf                          -   filter keep if:
  ċ                            -     count (spaces)          ["Sue ","Sue N","Sue Ng"]
        ⁶                      -   literal space character   ' '
      t€                       -   trim from €ach            ["Sue","Sue N","Sue Ng"]
                 ”.            -   literal period character  '.'
                ¦              -   sparse application...
         ;€                    -   ...of: concatenate €ach (with a period)
                               -   ...only for these indexes:
               $               -     last two links as a monad:
           J                   -       range of length       [1,2,3]
              $                -       last two links as a monad:
            Ṗ                  -         pop                 [1,2]
             Ḋ                 -         dequeue             [2]  (i.e. 2,3,...,length-1)
                               -   ...i.e.:                  ["Sue","Sue N.","Sue Ng"]
                               -                   yielding: [["Sam","Sam N.","Sam Ng"],["Sam","Sam L.","Sam Li"],["Sue","Sue N.","Sue Ng"]]
                           $   - last two links as a monad:
                          Ẏ    -   tighten                   ["Sam","Sam N.","Sam Ng","Sam","Sam L.","Sam Li","Sue","Sue N.","Sue Ng"]
                       ÐṂ€     -   filter keep minimals for €ach: 
                     ċ@        -     count (sw@ping args)    [["Sam N.","Sam Ng"],["Sam L.","Sam Li"],["Sue","Sue N.","Sue Ng"]]
                            Ḣ€ - head €ach                   ["Sam N.","Sam L.","Sue"]

Python 2, 130 bytes

def f(a):n=[[x[:i]+'.'*(' 'in x[:i]<x)for i in range(x.find(' '),len(x)+1)]for x in a];print[min(x,key=sum(n,[]).count)for x in n]

Try it online!

First generates all the nicknames, as follows:

n == [
    ['John', 'John .', 'John C.', 'John Cl.', 'John Cla.', 'John Clan.', 'John Clanc.', 'John Clancy'],
    ['Julie', 'Julie .', 'Julie W.', 'Julie Wa.', 'Julie Wal.', 'Julie Walk.', 'Julie Walke.', 'Julie Walker'],
    ['John', 'John .', 'John W.', 'John Wa.', 'John Wal.', 'John Walk.', 'John Walke.', 'John Walker'],
    ['Julie', 'Julie .', 'Julie C.', 'Julie Cl.', 'Julie Cla.', 'Julie Clan.', 'Julie Clanc.', 'Julie Clancy'],
    ['Jill', 'Jill .', 'Jill D.', 'Jill De.', 'Jill Des.', 'Jill Desm.', 'Jill Desmo.', 'Jill Desmon.', 'Jill Desmond']

Then picks the first* one from each list that is least frequent in sum(n,[]). This will always be the first unique nickname.

Note that n includes the erroneous nicknames 'John .' etc., but they will never be picked.

(*CPython 2.7’s min does so, anyway. This code may not be portable!)


Ruby 165 162 161 160 bytes

Includes 1 trailing space if only the given name is returned, eg. "John "

->a,n=0,s=0{a.group_by{|i|i[n]}.values.flat_map{|i|j=i[0];k=j.index' ';i.size<2?j.size>n ?j[0,[n+1,k].max-(s>1?0:1)]+(n>k ??.:''):j:f[i,n+=1,i.count{|l|l[n]}]}}

Try it online!

163 bytes if you don't want the trailing space

->a,n=0,s=0{a.group_by{|i|i[n]}.values.flat_map{|i|j=i[0];k=j.index' ';i.size<2?j.size>n ?j[0..[n,k-1].max-(s>1?0:1)]+(n>k ??.: ''):j:f[i,n+1,i.count{|l|l[n+1]}]}}

Try it online!


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.