8
\$\begingroup\$

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 :-).

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

15 Answers 15

5
\$\begingroup\$

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&

Try it online.

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.
\$\endgroup\$
  • \$\begingroup\$ Can you add a link to test it please? I'm on mobile. \$\endgroup\$ – Cthanatos May 24 '15 at 21:22
  • \$\begingroup\$ @Cthanatos Added. \$\endgroup\$ – jimmy23013 May 24 '15 at 21:26
  • 1
    \$\begingroup\$ r pushes an empty string on EOF, so this works as well: r{(\eu_elf&Sr}h; \$\endgroup\$ – Dennis May 25 '15 at 0:37
  • 1
    \$\begingroup\$ @Dennis I'm sure I have seen code like that many times, but still didn't remember... Thanks. But the ; makes no sense then. \$\endgroup\$ – jimmy23013 May 25 '15 at 0:44
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – Dennis May 25 '15 at 2:02
4
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ Is this duplicating hyphens? \$\endgroup\$ – Cthanatos May 24 '15 at 21:19
  • \$\begingroup\$ @Cthanatos Should work now. \$\endgroup\$ – Jakube May 24 '15 at 21:25
  • \$\begingroup\$ @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? \$\endgroup\$ – Cthanatos May 24 '15 at 21:45
  • \$\begingroup\$ @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..." \$\endgroup\$ – grovesNL May 24 '15 at 21:54
  • \$\begingroup\$ Touché... Good point. \$\endgroup\$ – Cthanatos May 24 '15 at 21:56
2
\$\begingroup\$

Python 3.4, 94 92 82 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

\$\endgroup\$
  • \$\begingroup\$ 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()]) \$\endgroup\$ – FryAmTheEggman May 24 '15 at 23:29
  • \$\begingroup\$ @FryAmTheEggman Ah, thanks! I forgot about starred argument passing. \$\endgroup\$ – Robotato May 25 '15 at 0:31
  • 2
    \$\begingroup\$ 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. :^) \$\endgroup\$ – DLosc May 25 '15 at 3:22
  • \$\begingroup\$ @DLosc That string-slicing trick is clever, thanks! I'll have to remember that one. \$\endgroup\$ – Robotato May 25 '15 at 5:51
2
\$\begingroup\$

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!

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

sed (39 chars)

Just a couple of regular expressions:

sed 's+\<\(.\)[A-Za-z]*+\1+g;s+  *+ +g'
\$\endgroup\$
  • 2
    \$\begingroup\$ 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. \$\endgroup\$ – manatwork May 25 '15 at 7:39
1
\$\begingroup\$

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...

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

PowerShell, 56 bytes

%{($_-split' '|%{$_[0]+($_-replace'[a-z]','')})-join' '}
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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.
\$\endgroup\$
1
\$\begingroup\$

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.

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

Perl 5, 34 bytes

33 bytes code + 1 for -p.

s!\S\K\S+| \K +!$&=~s/\w| //gr!ge

Try it online!

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

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.
\$\endgroup\$
0
\$\begingroup\$

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
\$\endgroup\$
0
\$\begingroup\$

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)]
\$\endgroup\$
-1
\$\begingroup\$

Perl 6, 15 bytes

s:g/(\w)\w+/$0/

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Output doesn't match the example. \$\endgroup\$ – Xcali Oct 19 '17 at 22:23

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.