30
\$\begingroup\$

Note: The winning answer will be selected on 4/12/17 the current winner is Jolf, 1 byte.

I'm surprised that we haven't had a what's my middle name challenge on this site yet. I did alot of searching but found nothing. If this is a dup, please flag it as such.

Your challenge

Parse a string that looks like Jo Jean Smith and return Jean.

Test cases

Input: Samantha Vee Hills
Output: Vee

Input: Bob Dillinger
Output: (empty string or newline)

Input: John Jacob Jingleheimer Schmidt
Output: Jacob Jingleheimer

Input: Jose Mario Carasco-Williams
Output: Mario

Input: James Alfred Van Allen
Output: Alfred Van 

(That last one is incorrect technically, but fixing that would be too hard.)

Notes:

  • Names will always have at least 2 space-separated parts, with unlimited middle names between them or can be a list/array of strings.
  • Names may contain the alphabet (case-insensitive) and - (0x2d)
  • You may output a trailing newline.
  • You may require input to have a trailing newline.
  • Input from STDIN, a function parameter, or command-line argument is allowed, but hard-coding it in is not allowed.
  • Standard loopholes forbidden.
  • Output may be function return value, STDOUT, STDERR, etc.
  • Trailing spaces/newlines/tabs in the output are allowed.
  • Any questions? Comment below!

This is , so the shortest anwser in bytes wins!

\$\endgroup\$
  • 2
    \$\begingroup\$ Can the output be a list of strings? \$\endgroup\$ – Anthony Pham Apr 2 '17 at 14:34
  • 5
    \$\begingroup\$ If other formats than a space-separated string are allowed, please edit that into the specification. \$\endgroup\$ – Martin Ender Apr 2 '17 at 14:46
  • 5
    \$\begingroup\$ @programmer5000: if the input can be a list of strings, how about the output? Is ["John", "Jacob", "Jingleheimer", "Schmidt"] -> ["Jacob", "Jingleheimer"] a valid solution? \$\endgroup\$ – nimi Apr 2 '17 at 15:17
  • 3
    \$\begingroup\$ Are leading spaces allowed? \$\endgroup\$ – betseg Apr 2 '17 at 15:32
  • 2
    \$\begingroup\$ @DJ Because "Van" isn't his middle name, it's part of his last name. A particularly vexing case is David Lloyd George, whose first name is David and last name is Lloyd George. Any attempt to parse real people's names like this is doomed. In fact, you can't even tell what the first and last names are (think Li Shi). \$\endgroup\$ – David Conrad Apr 3 '17 at 2:16

58 Answers 58

2
\$\begingroup\$

APL (Dyalog), 8 6 bytes

¯1↓1↓⊢

Try it online!

This is a tacit train.

Explanation

When is a dyad, it returns all but the first/last n elements of its vector argument.

   1↓                  ⍝ Remove the first element in the 
     ⊢                 ⍝ right argument
¯1↓                    ⍝ and remove the last element
\$\endgroup\$
2
\$\begingroup\$

Bash, 31 19 bytes

echo ${@:2:$[$#-2]}

Try it online!

Breakdown:

Prints parameter expansion from second to second last element.

Edit

Removed commented code from breakdown section, since it's now just one line long.

-12 bytes thanks to Neil

\$\endgroup\$
  • \$\begingroup\$ Can you not just echo the expression in the first line directly? \$\endgroup\$ – Neil Apr 2 '17 at 18:57
  • \$\begingroup\$ @Neil How can I do that, if the result of the expression is not $@? \$\endgroup\$ – Maxim Mikhaylov Apr 2 '17 at 19:13
  • \$\begingroup\$ Surely set -- assigns the result of the expression to $@? \$\endgroup\$ – Neil Apr 2 '17 at 21:32
  • \$\begingroup\$ @Neil Took me way too long to understand what you mean. This is embarrasing... \$\endgroup\$ – Maxim Mikhaylov Apr 2 '17 at 23:26
2
\$\begingroup\$

Grime, 6 bytes

<\ 0\ 

Try it online! Note the trailing space.

Explanation

        Match a substring S that satisfies:
<       S is contained in a string of the form
 \      a space
   0    then S
    \   then another space.

This matches a substring that's surrounded by spaces. By default, Grime prints the longest match it finds (without the spaces). If no match exists, nothing is printed.

\$\endgroup\$
2
\$\begingroup\$

REXX, 42 bytes

arg a
say delword(delword(a,words(a)),1,1)
\$\endgroup\$
1
\$\begingroup\$

Batch, 70 bytes

@set s=.
:l
@if not "%3"=="" set s=%s% %2&shift&goto l
@echo(%s:~2%

The loop concatenates arguments starting with the second, shifting them until the third argument is empty. This results in a leading space, so to remove that I prepend with a . so that I can slice the string (slicing an empty string produces an erroneous result in Batch). If a trailing space on output is acceptable, then for 66 bytes:

@set s=
:l
@if not "%3"=="" set s=%s%%2 &shift&goto l
@echo(%s%
\$\endgroup\$
1
\$\begingroup\$

Ruby, 33 bytes

->s{$><<s.split[1..-2].join(' ')}
\$\endgroup\$
1
\$\begingroup\$

TI-Basic (TI-84 Plus CE), 131 bytes

Prompt Str0
inString(Str0," →A
length(Str0)–A→L
sub(Str0,A,L→Str0
" →Str2
For(B,1,L
sub(Str0,B,1)+Str2→Str2
End
inString(Str2," →A
L-A→L
sub(Str2,A,L→Str2
" →Str0
For(B,1,L
sub(Str2,B,1)+Str0→Str0
End
Disp Str0

Explanation:

Prompt Str0              # 4 bytes, input user string
inString(Str0," →A       # 10 bytes, store the index of the first space in A
length(Str0)–A→L         # 10 bytes, store the length of the string (after removing the first A characters) in L
sub(Str0,A,L→Str0        # 12 bytes, remove first A-1 and last characters of Str0
" →Str2                  # 6 bytes, temporary string to reverse Str0
For(B,1,L                # 7 bytes, reverse Str0 into Str2
sub(Str0,B,1)+Str2→Str2  # 16 bytes
End                      # 2 bytes
inString(Str2," →A       # 10 bytes, store the index of the first space in A
L-A→L                    # 6 bytes, get new length
sub(Str2,A,L→Str2        # 12 bytesremove first A-1 and last characters of Str2
" →Str0                  # 6 bytes, temporary string to reverse Str2
For(B,1,L                # 7 bytes, reverse Str2 into Str0
sub(Str2,B,1)+Str0→Str0  # 16 bytes
End                      # 2 bytes
Disp Str0                # 3 bytes, display final string with (2 trailing spaces)
\$\endgroup\$
1
\$\begingroup\$

Python 3, 28 bytes

print(input().split()[1:-1])

Try it online!

\$\endgroup\$
1
\$\begingroup\$

CJam, 6 bytes

{1>W<}

Anonymous block that expects an array of strings on the stack, and leaves an array of strings after.

Try it online!

Explanation

1>    e# Slice the array after the first element
  W<  e# Slice the array before the last element
\$\endgroup\$
1
\$\begingroup\$

Ruby, 17 bytes

$><<$*[1..-2]*' '

Full program, takes input as command line arguments, e.g.:

$ ruby middle.rb john jacob jingleheimer shmidt
jacob jingleheimer

If we don't mind having the result wrapped in quotation marks, can just use:

p$*[1..-2]*' '
$ ruby middle2.rb john jacob jingleheimer shmidt
"jacob jingleheimer"

Of course, we can also just take a list and return a list, which can be as short as a 13 byte lambda.

->s{s[1..-2]}
# usage:
y = ->s{s[1..-2]};
y.call ["john","jacob","jingleheimer","shmidt"] #=> ["jacob", "jingleheimer"]
\$\endgroup\$
1
\$\begingroup\$

Sed, 23 20 bytes

s/\w* (.*) \w*$/\1/

Unlike my last sed entry which involved a pipeline from one sed command to another, this one is just a simple, single command, so I'm only counting the bytes of the sed script.

Edited: Plus a 1-byte penalty for the -r flag. Thank you, Krixti Lithos, for pointing that out!

\$\endgroup\$
  • \$\begingroup\$ Can you use the -r flag to save some bytes from escaping the groups? \$\endgroup\$ – Kritixi Lithos Apr 3 '17 at 8:22
  • \$\begingroup\$ @Kritixi I could but I'm not sure how to score that. Does it count as 2 bytes for the -r flag or only 1 byte? \$\endgroup\$ – David Conrad Apr 4 '17 at 5:37
  • \$\begingroup\$ It counts as only 1 byte \$\endgroup\$ – Kritixi Lithos Apr 4 '17 at 5:39
  • \$\begingroup\$ @Kritixi Thanks! I just found this answer on meta, too. And I see another change I can make to improve it as well. \$\endgroup\$ – David Conrad Apr 4 '17 at 5:44
1
\$\begingroup\$

Ruby, 13 bytes

->s{s[1..-2]}

The author confirmed in comments that the input and output can be arrays.

\$\endgroup\$
1
\$\begingroup\$

Pushy, 17 bytes

32K-$.;@$.;.@32+"

Try it online!

32 K-    \ Take away 32 from every character.
         \ Now we have the value 0 where there were spaces.
$        \ Until we reach a zero:
 .;      \   Pop a character from the end
         \ Everything after the last space is now removed
@        \ Reverse stack
$.;      \ Do the same
.        \ Pop the leading space
32+      \ Add 32 to everything to map the numbers back to their original characters
@"       \ Reverse and print

This is the first method I thought of, and looks like the shortest.

\$\endgroup\$
1
\$\begingroup\$

C#, 72 69 bytes

Takes a string, returns a string...

s=>string.Join(" ",s.Split(' ').Skip(1).TakeWhile(n=>!s.EndsWith(n)))

C# 43 bytes

Takes a string array, returns a string array...

s=>s.Skip(1).TakeWhile((n,i)=>i<s.Length-2)
\$\endgroup\$
1
\$\begingroup\$

c, 72 bytes

g(char*p){char*e,*s=0;for(;*p;p++)*p-32?0:s?(e=p):(s=p);*e=0;puts(s+1);}

Try it online

\$\endgroup\$
1
\$\begingroup\$

Clojure, 107 bytes

(fn[f](clojure.string/join" "(map #(apply str %)(drop 1(drop-last(take-nth 2(partition-by #(= % \ )f)))))))

Unfortunately drop/drop-last was shorter than subvec.

(defn middle-name [full-name]
  ; Partition the string into a list of names split on spaces, then take every second element
  ;  since partition keeps the spaces 
  (let [sub-names (take-nth 2
                    (partition-by #(= % \ ) full-name))]

    ; ... then join the middle names together on a space.
    (clojure.string/join " "
      ; Drop returns list of chars, so turn them back into strings...
      (map #(apply str %)
           ; Drop the first and last name
           (drop 1
             (drop-last sub-names))))))
\$\endgroup\$
1
\$\begingroup\$

Japt, 3 bytes

ůJ

Try it or run all test cases

\$\endgroup\$
  • \$\begingroup\$ Alternative: s1J \$\endgroup\$ – Oliver Dec 14 '18 at 15:29
  • \$\begingroup\$ Oh, I posted an answer over a year ago. I'm gonna update it to s1J if you don't mind. \$\endgroup\$ – Oliver Dec 14 '18 at 15:43
1
\$\begingroup\$

Japt, 7 3 bytes

s1J

Try it online!

This is essentially Input.slice(1,-1). The -1 wraps around to the last item in the input.

\$\endgroup\$
1
\$\begingroup\$

Powershell, 32 bytes

''+($args|sls ' .+ '|% m*)|% t*m

Test script:

$f = {
''+($args|sls ' .+ '|% m*)|% t*m
}

@(
    ,("Samantha Vee Hills"    ,"Vee")
    ,("Bob Dillinger"    ,"")
    ,("John Jacob Jingleheimer Schmidt"    ,"Jacob Jingleheimer")
    ,("Jose Mario Carasco-Williams"    ,"Mario")
    ,("James Alfred Van Allen"    ,"Alfred Van")
) | % {
    $name,$expected = $_
    $result = &$f $name
    "$($result-eq$expected): $expected"
}

Output:

True: Vee
True:
True: Jacob Jingleheimer
True: Mario
True: Alfred Van
\$\endgroup\$
1
\$\begingroup\$

C (gcc), 144 139 91 86 bytes

y,z;char*f(char*s){for(y=0;*++s-32;);for(;s[y];y++)z=s[y]-32?z:y;z[s]=0;return!!*s+s;}

Try it online!

-48 bytes by learning C over the past year and a half since I first posted this

-7 bytes from Jonathan Frech

A function that takes in a char* and outputs a char* corresponding to the (character after the) first space in the string, but also edits the string so that it's last space is replaced with \0.

Note: this function will segfault if given a string without a space in it.

Full program:

y;z;char*f(char*s){y=0;while(*++s-32);while(s[y]){z=s[y]-32?z:y;y++;}s[z]=0;return s+!!*s;}
int main(int argc, char *argv[]){
	for (int i = 1; i < argc; ++i)
		printf("%s\n",f(argv[i]));
}

Un-golfed:

char *middle(char* name) {
	int index = 0, lastspace;
	while(name[0] != ' ') // move name pointer forward to the first space
		++name;
	while(name[index] != '\0') { // find the index in the (new) string of the last space
		if (name[index] == ' ') lastspace = index;
		index++;
	}
	name[lastspace] = '\0'; // Terminate the string at the last space
	if (name[0] == '\0') return name; // If the last space was the first space, return the empty string
	else return name + 1; // Else, return the new string
}

Try it online!

\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 16 Bytes

x=>x.slice(1,-1)

Simple. Return the array passed from the second element to the second from last.

\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG! Nice submission! \$\endgroup\$ – programmer5000 Apr 5 '17 at 17:30
0
\$\begingroup\$

Lua, 39 bytes

print(io.read("*l"):match(" (.+) .+$"))
\$\endgroup\$
0
\$\begingroup\$

c, 53 bytes

main(a,b)char**b;{for(++b;--a>2;printf("%s ",*++b));}

Try it online

\$\endgroup\$
0
\$\begingroup\$

Noodel, 5 bytes

Input must be an array of the names.

Ẹ⁻2¤İ

Try it:)


How it works

      # Pushes the input on implicitly.
Ẹ⁻2¤İ
Ẹ     # Takes the last item of an array and pushes it to the back.
 ⁻2   # Pop the first two items off of the array.
   ¤  # Push the string "¤" onto the stack which represents a space.
    İ # Concatenates the array elements by the "¤" string.
      # Implicitly output the top of the stack to the screen.

<div id="noodel" code="Ẹ⁻2¤İ" input='["James", "Alfred", "Van", "Allen"]' cols="10" rows="2"/>

<script src="https://tkellehe.github.io/noodel/noodel-latest.js"></script>
<script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script>

\$\endgroup\$
0
\$\begingroup\$

Javascript ES6 23Bytes

x=>x.pop()*x.shift()||x

use * instead of && to save 1 byte

Try it online

\$\endgroup\$
0
\$\begingroup\$

Tcl, 28 bytes

proc R n {lrange $n 1 end-1}

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Gambit Scheme (gsi), 48 bytes

(lambda(x)(if(>(length x)2)(cadr(reverse x))""))

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Clojure, 43 bytes:

#(drop 1(butlast(read-string(str"("%")"))))

Here we read string as an edn data, then choosing its center.

Or for stdout, 57 bytes:

#(apply pr-str(drop 1(butlast(read-string(str"("%")")))))



You can also check it here.

\$\endgroup\$
  • \$\begingroup\$ Is the space in str " necessary? \$\endgroup\$ – Jonathan Frech Dec 14 '18 at 16:50
  • \$\begingroup\$ @JonathanFrech it leads to "RuntimeException Unmatched delimiter: ) clojure.lang.Util.runtimeException (Util.java:221)" without space \$\endgroup\$ – bbb1 Dec 14 '18 at 16:55
  • \$\begingroup\$ @JonathanFrech I add link to online Clojure REPL, so you can check it. UPD: where it works... It's strange. \$\endgroup\$ – bbb1 Dec 14 '18 at 16:57
  • \$\begingroup\$ To me it looks like you changed it in your online REPL, did not change your post and said it would not work ... (TIO). \$\endgroup\$ – Jonathan Frech Dec 14 '18 at 17:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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