19
\$\begingroup\$

This is similar to Making an acronym, but there are several key differences, including the method of fetching the acronym, and this challenge including flexible output.

Task

Given a string (list of chars/length 1 strings is allowed) containing only printable ASCII, output all capital letters in the input that are either preceded by a space or a dash, or are the first character in the input. Empty string is undefined behavior.

Test Cases:

Output may be in the format of "TEST", ["T","E","S","T"], or whatever else works for you.

Self-contained Underwater Breathing Apparatus
SUBA

a Programming Language
PL

NATO Atlantic TREATY Organization
NATO

DEFCON 2
D

hello, world!


light-Emitting dioDe
E

What Does the Fox Say?
WDFS


3D mov-Ies
I

laugh-Out Lou-D
OLD

Best friends FOREVE-r
BF

--


<space>


--  --a -  - --


--  -- -  - -- A
A

Step-Hen@Gmail-Mail Mail.CoM m
SHMM

This is , so shortest answer in bytes wins.

\$\endgroup\$
5
  • \$\begingroup\$ Sandbox \$\endgroup\$
    – Stephen
    Jul 21, 2017 at 13:21
  • \$\begingroup\$ Can we take input as a list of Strings (list of characters)? \$\endgroup\$
    – Mr. Xcoder
    Jul 21, 2017 at 13:43
  • \$\begingroup\$ @Mr.Xcoder yes. \$\endgroup\$
    – Stephen
    Jul 21, 2017 at 13:45
  • \$\begingroup\$ Could you add a test case that includes some letters separated by one or more characters that aren't letters, numbers, spaces or dashes. An e-mail address, for example: My-Name@Some-Domain.TLD. \$\endgroup\$
    – Shaggy
    Jul 21, 2017 at 16:12
  • 1
    \$\begingroup\$ @Shaggy added, thanks. \$\endgroup\$
    – Stephen
    Jul 21, 2017 at 17:10

34 Answers 34

8
\$\begingroup\$

V, 7 bytes

ÍÕü¼À!õ

Try it online!

Here is a hexdump to prove the byte count:

00000000: cdd5 fcbc c021 f5                        .....!.

Explanation:

Í       " Search and replace all occurrences on all lines:
        " (Search for)
 Õ      "   A non-uppercase letter [^A-Z]
  ü     "   OR
      õ "   An uppercase letter
    À!  "   Not preceded by...
   ¼    "   A word-boundary
        " (implicitly) And replace it with:
        "   Nothing

This is short all thanks to V's wonderful regex compression.

\$\endgroup\$
3
  • \$\begingroup\$ That's pretty short 0.o \$\endgroup\$
    – Stephen
    Jul 21, 2017 at 14:57
  • \$\begingroup\$ @StepHen Why thank you! I think this is pretty close to optimal. :) \$\endgroup\$
    – DJMcMayhem
    Jul 21, 2017 at 14:58
  • 2
    \$\begingroup\$ What do you mean by a word boundary? The question seems to suggest that only space and - are allowed. \$\endgroup\$
    – Neil
    Jul 21, 2017 at 15:44
8
\$\begingroup\$

R, 66 63 bytes

function(s)(s=substr(strsplit(s,' |-')[[1]],1,1))[s%in%LETTERS]

Try it online!

-3 bytes thanks to Scarabee

An anonymous function; returns the acronym as a vector c("N","A","T","O") which is implicitly printed.

For once, this isn't too bad in R! splits on - or (space), takes the first element of each of those, and then returns whichever ones are capitals (LETTERS is an R builtin with the capital letters), in order.

\$\endgroup\$
2
  • \$\begingroup\$ I think you can save a few bytes: function(s)(s=substr(strsplit(s,' |-')[[1]],1,1))[s%in%LETTERS] \$\endgroup\$
    – Scarabee
    Jul 23, 2017 at 0:00
  • 1
    \$\begingroup\$ @Scarabee thank you. sorry it took 2 years to update. \$\endgroup\$
    – Giuseppe
    Jul 18, 2019 at 16:09
6
\$\begingroup\$

Python 2, 59 56 bytes

-3 bytes thanks to Lynn

lambda s:[b for a,b in zip(' '+s,s)if'@'<b<'['>a in' -']

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ I borrowed your trick '@'<b<'[', very nice solution +1 \$\endgroup\$
    – Mr. Xcoder
    Jul 21, 2017 at 13:36
  • \$\begingroup\$ Don’t forget about comparison chaining! '@'<b<'['>a in' -' saves 3 bytes. \$\endgroup\$
    – Lynn
    Jul 21, 2017 at 14:50
5
\$\begingroup\$

Javascript 21 bytes

Takes a string input and outputs an array of strings containing the acronym characters

x=>x.match(/\b[A-Z]/g)

Explanation

It's just a global regex match for word-boundary followed by a capital letter.

\$\endgroup\$
4
\$\begingroup\$

Retina, 21 17 bytes

!`(?<=^| |-)[A-Z]

Try it online!

Explanation

Outputs the matches of the regex (?<=^| |-)[A-Z] in the input, one per line (!).

\$\endgroup\$
4
\$\begingroup\$

Dyalog APL, 29 23 bytes

Bonus test case: A Programming Language (APL).

'(?<=^| |-)[A-Z]'⎕S'&'⊢

Returns an array of chars (shows as space seperated on TIO).

Try it online!


Older post, 29 bytes

{(⎕AV~⎕A)~⍨'(\w)\w+'⎕R'\1'⊢⍵}

Try it online!

How?

'(\w)\w+'⎕R - replace each cluster of alphabetic chars

    '\1' - with its first character

~⍨ - remove every char

    (⎕AV~⎕A) - that is not an ASCII uppercase

\$\endgroup\$
3
\$\begingroup\$

Python, 53 bytes

import re
lambda s:re.findall("(?<=[ -])[A-Z]"," "+s)

Try it online!

A simple regular expression with a lookahead for space or dash. Rather than matching the start, prepend a space.

\$\endgroup\$
3
  • \$\begingroup\$ Edited in a TIO link with MrXCoder's test suite. \$\endgroup\$
    – Stephen
    Jul 21, 2017 at 13:54
  • \$\begingroup\$ Thanks @StepHen -- you beat me to it and saved me the effort \$\endgroup\$
    – Chris H
    Jul 21, 2017 at 13:55
  • \$\begingroup\$ 50 \$\endgroup\$ Jul 18, 2019 at 14:55
3
\$\begingroup\$

C#, 84 78 bytes

using System.Linq;s=>s.Where((c,i)=>c>64&c<91&(i>0?s[i-1]==32|s[i-1]==45:1>0))

Saved 6 bytes thanks to @jkelm.

Try it online!

Full/Formatted Version:

using System.Collections.Generic;
using System.Linq;

class P
{
    static void Main()
    {
        System.Func<string, IEnumerable<char>> f = s => s.Where((c, i) => c > 64 & c < 91 & (i > 0 ? s[i-1] == 32 | s[i-1] == 45: 1 > 0));

        System.Console.WriteLine(string.Concat(f("Self-contained Underwater Breathing Apparatus")));
        System.Console.WriteLine(string.Concat(f("a Programming Language")));
        System.Console.WriteLine(string.Concat(f("NATO Atlantic TREATY Organization")));
        System.Console.WriteLine(string.Concat(f("DEFCON 2")));
        System.Console.WriteLine(string.Concat(f("hello, world!")));
        System.Console.WriteLine(string.Concat(f("light-Emitting dioDe")));
        System.Console.WriteLine(string.Concat(f("What Does the Fox Say?")));
        System.Console.WriteLine(string.Concat(f("3D mov-Ies")));
        System.Console.WriteLine(string.Concat(f("laugh-Out Lou-D")));
        System.Console.WriteLine(string.Concat(f("Best friends FOREVE-r")));
        System.Console.WriteLine(string.Concat(f(" ")));
        System.Console.WriteLine(string.Concat(f("--  --a -  - --")));
        System.Console.WriteLine(string.Concat(f("--  -- -  - -- A")));

        System.Console.ReadLine();
    }
}
\$\endgroup\$
8
  • \$\begingroup\$ Why do you have to include using System.Linq in the byte count if using System.Collections.Generic is exempt? Is there some consensus on which using's are countable? \$\endgroup\$
    – user20151
    Jul 21, 2017 at 14:04
  • \$\begingroup\$ @DaveParsons using System.Linq; is needed for the Linq code in my answer. However, IEnumerbale<char> is not part of the answer and that is the part of the code that needs using System.Collections.Generic; to compile. \$\endgroup\$ Jul 21, 2017 at 14:05
  • \$\begingroup\$ makes sense; thanks for clarification. \$\endgroup\$
    – user20151
    Jul 21, 2017 at 14:08
  • \$\begingroup\$ You could save a few bytes by checking uppercase using the chars as ints. c>64&c<91 should net you 6 bytes. \$\endgroup\$
    – jkelm
    Jul 21, 2017 at 14:47
  • \$\begingroup\$ @jkelm Nice :) I always forget about that trick! \$\endgroup\$ Jul 21, 2017 at 14:49
3
\$\begingroup\$

Julia 0.6.0 (57 bytes)

s=split(s,r" |-");for w∈s isupper(w[1])&&print(w[1])end

Explanation: This is my first code-golf. Pretty straight forward. Split the words, print 1rst upper letter of each.

Probably easy to do better using regex but I am new to this

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Welcome to PPCG! I'm out of votes right now, I'll upvote this later. \$\endgroup\$
    – Stephen
    Jul 21, 2017 at 20:40
  • 2
    \$\begingroup\$ @StepHen I've gotchoo covered. :P \$\endgroup\$
    – DJMcMayhem
    Jul 21, 2017 at 20:42
2
\$\begingroup\$

05AB1E, 11 bytes

'-ð‡ð¡ζнAuÃ

Try it online!

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

C# (.NET Core), 108 bytes

n=>{var j="";n=' '+n;for(int i=0;++i<n.Length;)if(" -".IndexOf(n[i-1])>=0&n[i]>64&n[i]<91)j+=n[i];return j;}

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ Haven't checked but changing the if to a ternary might save you bytes. This starts at index 2 instead of 1, just change int i=1 to int i=0 to fix it. Other than that I don't think there's much more you can do here. \$\endgroup\$ Jul 21, 2017 at 15:00
  • \$\begingroup\$ A ternary wouldn't help here, as it would be the same byte count as an if statement. However, you are correct in that I need to change the initial i value \$\endgroup\$
    – jkelm
    Jul 21, 2017 at 15:11
  • \$\begingroup\$ I wasn't entirely sure but they usually come out shorter so it is always worth a check. \$\endgroup\$ Jul 21, 2017 at 15:12
2
\$\begingroup\$

Jelly,  11  10 bytes

-1 byte thanks to Erik the Outgolfer ( splits at spaces >_<)

⁾- yḲḢ€fØA

A monadic link taking and returning lists of characters.
As a full program accepts a string and prints the result.

Try it online! or see a test suite.

How?

⁾- yḲḢ€fØA - Link: list of characters, x       e.g. "Pro-Am Code-golf Association"
   y       - translate x with:
⁾-         -   literal list of characters ['-',' '] "Pro Am Code golf Association"
    Ḳ      - split at spaces               ["Pro","Am","Code","golf","Association"]
     Ḣ€    - head each (1st character of each)      "PACgA"
        ØA - yield uppercase alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
       f   - filter keep                            "PACA"
           - if running as a full program: implicit print
\$\endgroup\$
2
  • \$\begingroup\$ Umm, why not use instead of ṣ⁶? \$\endgroup\$ Jul 21, 2017 at 14:43
  • \$\begingroup\$ Heh, because I forgot about it. Thanks! \$\endgroup\$ Jul 21, 2017 at 14:44
2
\$\begingroup\$

Perl 5, 25 bytes

24 bytes code + 1 for -n.

Annoying that grep -P support variable length look-behind but Perl doesn't :(.

print/(?:^| |-)([A-Z])/g

-1 byte thanks to @Dada!

Try it online! - includes -l to run all tests at once.

\$\endgroup\$
3
  • \$\begingroup\$ You can do extremely way much so better: Try it online! ;-) \$\endgroup\$
    – Dada
    Jul 27, 2017 at 11:44
  • \$\begingroup\$ @Dada Hah! Of course... I'm out ATM but I'll update when I get back. Thanks! I'm quite disappointed I couldn't get s/// or $_= to negate the print... \$\endgroup\$ Jul 27, 2017 at 11:50
  • \$\begingroup\$ Yeah, I was looking for a single s/// to solve this but it's not obvious... I'm at work, maybe I'll give it another try later! \$\endgroup\$
    – Dada
    Jul 27, 2017 at 11:53
2
\$\begingroup\$

MATL, 19 bytes

'- 'X{&Yb'^[A-Z]'XX

Try it online!

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

Brachylog, 25 23 22 bytes

,Ṣ↻s₂ᶠ{h∈" -"&t.∧Ạụ∋}ˢ

Try it online!

(-2 bytes thanks to @Fatalize.)

,Ṣ↻                      % prepend a space to input
   s₂ᶠ                   % get all substrings of length 2 from that, to get prefix-character pairs
      {              }ˢ  % get the successful outputs from this predicate: 
       h∈" -"              % the prefix is - or space
               &t.∧        % then the character is the output of this predicate if:
                  Ạụ∋        % the alphabet uppercased contains the character
\$\endgroup\$
1
  • \$\begingroup\$ You can use instead of " " to save two bytes \$\endgroup\$
    – Fatalize
    Jul 30, 2018 at 6:41
2
\$\begingroup\$

Japt, 19 16 14 bytes

-2 bytes thanks to Shaggy

f/^| |-)\A/ mÌ

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Since you're using v2, I think you can change "(^| |-)%A" to /^| |-)\A/ to save a byte \$\endgroup\$ Jul 21, 2017 at 19:51
  • 1
    \$\begingroup\$ mf\A -> to save 2 bytes. \$\endgroup\$
    – Shaggy
    Jan 4, 2019 at 15:55
2
\$\begingroup\$

Swift 5, 110 bytes

-5 thanks to Cœur

import UIKit
func f(s:[String]){for i in zip(s,[" "]+s){if i.0.isUppercase()&&"- ".contains(i.1){print(i.0)}}}

Detailed Explanation

  • import Foundation - Imports the module Foundation that is vital for zip(), the main piece of this code.

  • func f(s:[String]){...} - Creates a function with a parameter s, that is a list of Strings, representing the characters of the input.

  • for i in zip(s,[" "]+s){...} - Iterates with i through the zip of the input and the input with a space added in the beginning, which is very helpful for getting the previous character in the String.

  • if - Checks whether:

    • i.0==i.0.uppercased() - The current character is uppercase,

    • &&"- ".contains(i.1) - and If the previous character is a space or a dash.

  • If the above conditions are met, then:

    • print(i.0) - The character is printed, because it is part of the acronym.
\$\endgroup\$
1
  • \$\begingroup\$ -5 with import UIKit instead of import Foundation. \$\endgroup\$
    – Cœur
    Jul 18, 2019 at 13:45
2
\$\begingroup\$

PowerShell, 43 bytes

''+($args|sls '(?<=^| |-)[A-Z]'-a -ca|% m*)

Try it online!

Unrolled:

''+($args|select-string '(?<=^| |-)[A-Z]' -allmatches -caseSensitive|% matches)
\$\endgroup\$
2
\$\begingroup\$

Python 3, 67 bytes

lambda x:[c[0]for c in x.replace("-"," ").split()if c[0].isupper()]

Try it online!

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

Python 3, 73 70 bytes

lambda n:[n[x]for x in range(len(n))if'@'<n[x]<'['and(' '+n)[x]in' -']

Try it online!


Explanation

  • lambda n: - Creates an anonymous lambda-function with a String parameter n.

  • n[x] - Gets the character of n at index x.

  • for x in range(len(n)) - Iterates from 0 to the length of n, naming the variable x.

  • if - Checks:

    • '@'<n[x]<'[' - If the character is uppercase,

    • and(' '+n)[x]in' -' - And if it is preceded by a space or a dash in the String formed by a space and n.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Is it bad that I read that as i supper, and I have no idea why? \$\endgroup\$ Jul 21, 2017 at 13:22
  • \$\begingroup\$ @TheLethalCoder It's .isupper(), I have no idea what you read :p \$\endgroup\$
    – Mr. Xcoder
    Jul 21, 2017 at 13:23
1
\$\begingroup\$

JavaScript (SpiderMonkey), 62 bytes

n=s=>(""+s.match(/([ -]|^)[A-Z]/g)).replace(/[ \-,]|null/g,"")

Try it online!

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

QuadS, 17 bytes

(?<=^| |-)[A-Z]
&

Try it online!

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

Pyth, 15 16 bytes

@rG1<R1:w"[ -]"3

Test suite

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

Pyth, 12 bytes

@rG1hMcXz\-d

Test suite here.

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

Bash (grep), 29 28 bytes

grep -oP'(?<=^| |-)[A-Z]' a

A port of my python answer but because pgrep supports variable length lookbehinds it's noticeably shorter (even accounting for the overhead of python). Stick the test cases in a file called a, output is 1 character per line.

-1 Thanks to Neil

\$\endgroup\$
2
  • \$\begingroup\$ ^| |- might be a shorter test? \$\endgroup\$
    – Neil
    Jul 21, 2017 at 15:43
  • \$\begingroup\$ @Neil that works here, thanks. Missed it because it doesn't work in Python \$\endgroup\$
    – Chris H
    Jul 21, 2017 at 15:58
1
\$\begingroup\$

RProgN 2, 18 bytes

`-` rû#ùr.'[a-z]'-

Explained

`-` rû#ùr.'[a-z]'-
`-`                     # Push "-" literal, and " " literal.
    r                   # replace, Replaces all "-"s with " "s.
     û                  # Split, defaultly by spaces.
      #ù                # Push the head function literally.
        r               # Replace each element of the split string by the head function, which gets each first character.
         .              # Concatenate, which collapses the stack back to a string.
          '[a-z]'-      # Push the string "[a-z]" literally, then remove it from the string underneith, giving us our output. 

Try it online!

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

PHP, 62 bytes

for(;~$c=$argn[$i++];$p=$c!="-"&$c!=" ")$c<A|$c>Z|$p?:print$c;

Run as pipe with -nR or try it online.

other solutions:

foreach(preg_split("#[ -]#",$argn)as$s)$s[0]>Z|$s<A?:print$s[0];  # 64 bytes
preg_match_all("#(?<=\s|-)[A-Z]#"," $argn",$m);echo join($m[0]);  # 64 bytes
preg_match_all("#(?<=\s|-)\p{Lu}#"," $argn",$m);echo join($m[0]); # 65 bytes
\$\endgroup\$
1
\$\begingroup\$

C++, 168 bytes

#include<string>
auto a=[](auto&s){auto r=s.substr(0,1);if(r[0]<65||r[0]>90)r="";for(int i=1;i<s.size();++i)if(s[i]>64&&s[i]<91&&(s[i-1]==32||s[i-1]==45))r+=s[i];s=r;};

Output done via the parameter

\$\endgroup\$
1
  • \$\begingroup\$ Would it be possible to completely remove #include<string> and assume the argument s is a std::string? \$\endgroup\$
    – Adalynn
    Oct 5, 2017 at 17:01
1
\$\begingroup\$

Lua, 79 75 bytes

for i=1,#t do for i in(" "..t[i]):gmatch"[%-| ]%u"do print(i:sub(2))end end

Try it!

I stuck a print() before the final end in the try it version because otherwise it's a mess. This program perfectly adheres to the requirements of I/O and matching, but without that extra new line it's pretty hard to read.

Input is given in the form of a table of number:string , number incrementing by 1 each time and starting at 1.

Explanation:

It for loops through a gmatch of each input string. The gmatch search is as follows:

[%-| ] - Group, search for a - or a space

%u - Search for an uppercase character

Then for each match, it prints it out minus the preceding dash or space

Edit: Golfed 4 bytes by removing the declaration of 'a' and adding the space to the input inside the for loop in, as well as changing the sub input to just 2 rather than 2,2 (which produce equivalent results)

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

Pyth, 12 bytes

Created one year after the initial answer.

rI#1hMcXQ\-d

Try it online!

Pyth, 21 bytes

Initial answer.

:+dQ"(?<=[ -])[A-Z]"1

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ -| is one byte less than [ -] \$\endgroup\$
    – ATaco
    Jul 23, 2017 at 23:45
  • \$\begingroup\$ @ATaco That does not seem to work \$\endgroup\$
    – Mr. Xcoder
    Jul 24, 2017 at 3:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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