# Take first letter of each word, leave spaces and punctuation

Shrink each word in a string of group of strings to single letters delineated by spaces or punctuation.

### Example

I'm a little teapot,  short and stout. Here is my handle, here is my spout. When I get all steamed up - hear me shout!   Tip me over and pour me out.


becomes

I' a l t, s a s. H i m h, h i m s. W I g a s u - h m s! T m o a p m o.


Edit - if there are multiple spaces, preserve only one space. All punctuation should be preserved, I missed the apostrophe. Yes this is code golf :-).

• Can there be multiple spaces between the words? Do we have to preserve them? May 24 '15 at 20:57
• Also, which characters exactly count as punctuation? May 24 '15 at 21:03
• What is the required behavior for numbers or other characters besides punctuation (+ etc.) May 24 '15 at 21:40
• Will there ever be more than one punctuation within a word? Something like O'Leary-Clarence-DeVois would become O'--? May 24 '15 at 21:42
• You can accept an answer whenever you like, but it's better to leave some time (days) before closing a challenge. May 24 '15 at 22:00

# CJam, 13 bytes

r{(\'A,f&Sr}h


Works if I can consider only the common punctuation characters, and the output can have trailing spaces. (Thanks to Dennis.)

This question needs much more clarification...

# CJam, 17 16 bytes

r{(\eu_elf&Sr}h&


### Explanation

r          e# Read one word from input.
{          e# While it is not EOF:
(\     e# Extract the first character.
eu     e# Convert the rest to uppercase.
_el    e# And lowercase.
f&     e# Delete characters in the first string if not in the second string.
S      e# Append a space.
r      e# Read the next word.
}h
&          e# Discard the last space by intersecting with empty string.

• Can you add a link to test it please? I'm on mobile. May 24 '15 at 21:22
• @Cthanatos Added. May 24 '15 at 21:26
• r pushes an empty string on EOF, so this works as well: r{(\eu_elf&Sr}h; May 25 '15 at 0:37
• @Dennis I'm sure I have seen code like that many times, but still didn't remember... Thanks. But the ; makes no sense then. May 25 '15 at 0:44
• If required, you could still get rid of it with &. Also, depending on what exactly counts as punctuation, '@, would be a shorter alternative to eu_el. May 25 '15 at 2:02

# Pyth, 14 bytes

jdm+hd-rtd0Gcz


Try it online: Demonstration

### Explanation:

                 implicit: z = input string
cz   split z by spaces
m              map each word d to:
hd              first letter of d
+                +
rtd0         (lowercase of d[1:]
-    G         but remove all chars of "abc...xyz")
jd               join resulting list by spaces and print

• Is this duplicating hyphens? May 24 '15 at 21:19
• @Cthanatos Should work now. May 24 '15 at 21:25
• @grovesNL can you think of a sentence that one might come across in regular writing ie a book, news article where numbers within a sentence might be an issue or come up? May 24 '15 at 21:45
• @Cthanatos: There are plenty of cases where numbers are used in books or news articles. "Over 200 respondents..." "The lot is 50 acres..." "It is capable of holding approximately 20 liters..." May 24 '15 at 21:54
• Touché... Good point. May 24 '15 at 21:56

# Python 3.4, 949282 77 bytes

print(*[w[0]+''.join(c[c.isalpha():]for c in w[1:])for w in input().split()])


I'm new to code golfing but I thought I'd give it a try! This one's not a winner, but it was fun.

This just splits the string, taking the first character of each word along with any punctuation in the rest of the word.

*edited with changes by FryAmTheEggman, DLosc

• You can use python's starred argument passing to save some bytes, and inverting the condition seems to save 1 byte (although it still looks suspiciously golfable). Here's what I got: print(*[w[0]+''.join([c for c in w[1:]if 1-c.isalpha()])for w in input().split()]) May 24 '15 at 23:29
• @FryAmTheEggman Ah, thanks! I forgot about starred argument passing. May 25 '15 at 0:31
• No need for the square braces around the inner comprehension--join can take a bare generator as an argument. Also, here's a string-slicing way of doing the "if not isalpha" logic: c[c.isalpha():]for c in w. Should get you down to 77 bytes. :^) May 25 '15 at 3:22
• @DLosc That string-slicing trick is clever, thanks! I'll have to remember that one. May 25 '15 at 5:51

# Jelly, 14 bytes

Ḣ;ḟØB$Ḳ¬ÐfÇ€K  Try it online! Solution done with Mr. Xcoder and caird coinheringaahing in Jelly Hypertraining chat room. Alternative 14 bytes: Try it online! # sed (39 chars) Just a couple of regular expressions: sed 's+\<$$.$$[A-Za-z]*+\1+g;s+ *+ +g'  • We usually not count the interpreter's name and the additional syntax required by shell to pass the code or data correctly to the interpreter. Your actual Sed code has only 32 characters. May 25 '15 at 7:39 # Lua - 126 characters Lua isn't much of a code golfing language, but I gave it a shot: a=''for b in string.gmatch( c, '%S+%s?' )do d=(b:match('%w')or''):sub(1,1)e=b:match('[^%s%w]')or''a=a..d..e..' 'end print( a )  This assumes that c is the string. Here it is cleaned up for readability: local string = [[I'm a little teapot, short and stout. Here is my handle, here is my spout. When I get all steamed up - hear me shout! Tip me over and pour me out.]] local final = '' for word in string.gmatch( string, '%S+%s?' ) do local first = ( word:match( '%w' ) or '' ):sub( 1, 1 ) local second = word:match( '[^%s%w]' ) or '' final = final .. first .. second .. ' ' end print( final )  You can test it here (copy and paste it. For the first on you also have to do c = "I'm a little ....) For some reason the online demo of Lua won't let you input variables using io.read... ## PowerShell, 56 bytes %{($_-split' '|%{$_[0]+($_-replace'[a-z]','')})-join' '}


# Javascript (ES6) 72 68 bytes

f=x=>x.split(/\s+/).map(x=>x.replace(/^(.)|[a-z]/gi,'$1')).join(' ') <input id="input" value="I'm a little teapot, short and stout. Here is my handle, here is my spout. When I get all steamed up - hear me shout! Tip me over and pour me out. " /> <button onclick="output.innerHTML=f(input.value)">Run</button> <br /><pre id="output"></pre> Commented: f=x=> x.split(/\s+/). // split input string by 1 or more spaces map(x=> // map function to resulting array x.replace(/^(.)|[a-z]/gi, '$1') // capture group to get the first character
// replace all other letters with empty string
).
join(' ') // join array with single spaces


## C99 - 170 169 bytes

main(_,a)char**a;{for(char*b=a[1],*c=b,*e,*d;*c++=*b;){for(e=b;*++b&&*b-32;);for(*b=0,d=strpbrk(e,"!',-."),d&&d-e?*c++=*d:0;b[1]==32;++b);++b;*c++=32;*c=0;}puts(a[1]);}


Ungolfed:

main(int argc, char**a) {
char*b=a[1],*c=b,*e,*d;
while(*c++=*b){
for(e=b;*++b&&*b-32;); //scan for first space or end of word
*b=0; //mark end of word
for(;b[1]==32;++b); //skip following spaces
d=strpbrk(e,"!',-."); //find punctuation
if(d&&d-e) //append punctuation if any, and it's not the word itself
*c++=*d;
*c++=32; //append space
b++;
}
*c=0; //mark end of line
puts(a[1]);
}


Usage:

gcc -std=c99 test.c -o test
./test "I'm a little teapot,  short and stout. Here is my handle, here is my spout. When I get all steamed up - hear me shout!   Tip me over and pour me out."


Output:

I' a l t, s a s. H i m h, h i m s. W I g a s u - h m s! T m o a p m o.


# Java 8, 87 bytes

s->{for(String x:s.split(" +"))System.out.print(x.replaceAll("^(.)|[a-z]+","$1")+" ");}  Explanation: Try it here. s->{ // Method with String parameter and no return-type for(String x:s.split(" +")) // Split the input on one or multiple spaces // And loop over the substrings System.out.print( // Print: x.replaceAll("^(.)|[a-z]+","$1")//    Regex to get the first letter + all non-letters
+" ");                          //    + a space delimiter
//  End of loop (implicit / single-line body)
}                                     // End of method


Regex explanation:

x.replaceAll("^(.)|[a-z]+","$1") x.replaceAll(" "," ") # Replace the match of String1 with String2, in String x " " # Regex to match: ^(.) # The first character of String x |[a-z]+ # Or any one or multiple lowercase letters " " # Replace with:$1   #  The match of the capture group (the first character)


So it basically removes all lowercase letters of a String, except the very first one.

# Perl 5, 34 bytes

33 bytes code + 1 for -p.

s!\S\K\S+| \K +!$&=~s/\w| //gr!ge  Try it online! # R, 46 45 bytes cat(gsub("^\\w\\W*\\K\\w*","",scan(,""),T,T))  This reads a line from STDIN and prints to STDOUT. It uses a regular expression to remove all characters after the first letter followed by any amount of punctuation. Ungolfed + explanation: # Read a string from STDIN and convert it to a character vector, # splitting at spaces input <- scan(what = "") # Replace stuff with nothing using a regex. # ^ start position anchor # \w single "word" character # \W* any amount of non-word (i.e. punctuation) characters # \K move the match position forward # \w* any number of word characters replaced <- gsub("^\\w\\W*\\K\\w*", "", input, ignore.case = TRUE, perl = TRUE) # Print the vector elements to STDOUT, separated by a space cat(replaced, sep = " ")  Example: > cat(gsub("^\\w\\W*\\K\\w*","",scan(,""),T,T)) 1: I'm a little teapot, short and stout. Here is my handle, here is my spout. When I get all steamed up - hear me shout! Tip me over and pour me out. I' a l t, s a s. H i m h, h i m s. W I g a s u - h m s! T m o a p m o.  # 05AB1E, 13 bytes #õKεćsDáмJ}ðý  Try it online! Explanation: #õKεćsDáмJ}ðý Full program # Split on spaces õK Remove empty strings from the list ε For each... ć push a[1:], a[0] s Swap D Duplicate á Push only letters of a м pop a,b => push a.remove(all elements of b) J Join } End for each ðý Join with spaces  VBA (Excel), 141 133 Bytes Using VBA Immediate Window, [A1] as Inputted Strings. z=" "&[A1]:for a=2 to len(z):c=mid(z,a,1):[A2]=[A2]&IIF(mid(z,a-1,1)=" ",c,IIF(asc(lcase(c))>96 and asc(lcase(c))<123,"",c)):next:?[TRIM(A2)]  z=" "&[a1]:for a=2 to len(z):c=mid(z,a,1):e=asc(lcase(c)):[a2]=[a2]&iif(mid(z,a-1,1)=" ",c,IIF((e>96)*(e<123),"",c)):next:?[TRIM(A2)]  # Perl 6, 15 bytes s:g/(\w)\w+/$0/


Try it online!

• Output doesn't match the example. Oct 19 '17 at 22:23