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 code-golf, so shortest answer in bytes wins.
34 Answers 34
V, 7 bytes
ÍÕü1⁄4À!õ
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...
1⁄4 " A word-boundary
" (implicitly) And replace it with:
" Nothing
This is short all thanks to V's wonderful regex compression.
-
\$\begingroup\$ That's pretty short 0.o \$\endgroup\$Stephen– Stephen2017年07月21日 14:57:26 +00:00Commented Jul 21, 2017 at 14:57
-
\$\begingroup\$ @StepHen Why thank you! I think this is pretty close to optimal. :) \$\endgroup\$DJMcMayhem– DJMcMayhem2017年07月21日 14:58:36 +00:00Commented 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– Neil2017年07月21日 15:44:43 +00:00Commented Jul 21, 2017 at 15:44
R, (削除) 66 (削除ここまで) 63 bytes
function(s)(s=substr(strsplit(s,' |-')[[1]],1,1))[s%in%LETTERS]
-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.
-
\$\begingroup\$ I think you can save a few bytes:
function(s)(s=substr(strsplit(s,' |-')[[1]],1,1))[s%in%LETTERS]\$\endgroup\$Scarabee– Scarabee2017年07月23日 00:00:43 +00:00Commented Jul 23, 2017 at 0:00 -
1\$\begingroup\$ @Scarabee thank you. sorry it took 2 years to update. \$\endgroup\$Giuseppe– Giuseppe2019年07月18日 16:09:04 +00:00Commented Jul 18, 2019 at 16:09
Python 2, (削除) 59 (削除ここまで) 56 bytes
-3 bytes thanks to Lynn
lambda s:[b for a,b in zip(' '+s,s)if'@'<b<'['>a in' -']
-
\$\begingroup\$ I borrowed your trick
'@'<b<'[', very nice solution +1 \$\endgroup\$Mr. Xcoder– Mr. Xcoder2017年07月21日 13:36:09 +00:00Commented Jul 21, 2017 at 13:36 -
\$\begingroup\$ Don’t forget about comparison chaining!
'@'<b<'['>a in' -'saves 3 bytes. \$\endgroup\$lynn– lynn2017年07月21日 14:50:11 +00:00Commented Jul 21, 2017 at 14:50
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.
Retina, (削除) 21 (削除ここまで) 17 bytes
!`(?<=^| |-)[A-Z]
Explanation
Outputs the matches of the regex (?<=^| |-)[A-Z] in the input, one per line (!).
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).
Older post, 29 bytes
{(⎕AV~⎕A)~⍨'(\w)\w+'⎕R'1円'⊢⍵}
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
Python, 53 bytes
import re
lambda s:re.findall("(?<=[ -])[A-Z]"," "+s)
A simple regular expression with a lookahead for space or dash. Rather than matching the start, prepend a space.
-
\$\begingroup\$ Edited in a TIO link with MrXCoder's test suite. \$\endgroup\$Stephen– Stephen2017年07月21日 13:54:03 +00:00Commented Jul 21, 2017 at 13:54
-
\$\begingroup\$ Thanks @StepHen -- you beat me to it and saved me the effort \$\endgroup\$Chris H– Chris H2017年07月21日 13:55:49 +00:00Commented Jul 21, 2017 at 13:55
-
\$\begingroup\$ 50 \$\endgroup\$negative seven– negative seven2019年07月18日 14:55:29 +00:00Commented Jul 18, 2019 at 14:55
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.
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();
}
}
-
\$\begingroup\$ Why do you have to include
using System.Linqin the byte count ifusing System.Collections.Genericis exempt? Is there some consensus on whichusing's are countable? \$\endgroup\$user20151– user201512017年07月21日 14:04:05 +00:00Commented 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 needsusing System.Collections.Generic;to compile. \$\endgroup\$TheLethalCoder– TheLethalCoder2017年07月21日 14:05:34 +00:00Commented Jul 21, 2017 at 14:05 -
\$\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– jkelm2017年07月21日 14:47:30 +00:00Commented Jul 21, 2017 at 14:47
-
\$\begingroup\$ @jkelm Nice :) I always forget about that trick! \$\endgroup\$TheLethalCoder– TheLethalCoder2017年07月21日 14:49:57 +00:00Commented Jul 21, 2017 at 14:49
-
\$\begingroup\$ No problem. You need every little thing you can get to be competitive in C# apparently. I have been avoiding Linq because of the using bloat, but it appears that didn't stop you :) \$\endgroup\$jkelm– jkelm2017年07月21日 14:54:47 +00:00Commented Jul 21, 2017 at 14:54
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
-
1\$\begingroup\$ Welcome to PPCG! I'm out of votes right now, I'll upvote this later. \$\endgroup\$Stephen– Stephen2017年07月21日 20:40:24 +00:00Commented Jul 21, 2017 at 20:40
-
2\$\begingroup\$ @StepHen I've gotchoo covered. :P \$\endgroup\$DJMcMayhem– DJMcMayhem2017年07月21日 20:42:30 +00:00Commented Jul 21, 2017 at 20:42
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;}
-
\$\begingroup\$ Haven't checked but changing the
ifto a ternary might save you bytes. This starts at index2instead of1, just changeint i=1toint i=0to fix it. Other than that I don't think there's much more you can do here. \$\endgroup\$TheLethalCoder– TheLethalCoder2017年07月21日 15:00:09 +00:00Commented 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– jkelm2017年07月21日 15:11:37 +00:00Commented 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\$TheLethalCoder– TheLethalCoder2017年07月21日 15:12:37 +00:00Commented Jul 21, 2017 at 15:12
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
-
\$\begingroup\$ Umm, why not use
Ḳinstead ofṣ6? \$\endgroup\$Erik the Outgolfer– Erik the Outgolfer2017年07月21日 14:43:24 +00:00Commented Jul 21, 2017 at 14:43 -
\$\begingroup\$ Heh, because I forgot about it. Thanks! \$\endgroup\$Jonathan Allan– Jonathan Allan2017年07月21日 14:44:15 +00:00Commented Jul 21, 2017 at 14:44
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.
-
\$\begingroup\$ You can do extremely way much so better: Try it online! ;-) \$\endgroup\$Dada– Dada2017年07月27日 11:44:07 +00:00Commented 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 theprint... \$\endgroup\$Dom Hastings– Dom Hastings2017年07月27日 11:50:02 +00:00Commented 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– Dada2017年07月27日 11:53:49 +00:00Commented Jul 27, 2017 at 11:53
Brachylog, (削除) 25 (削除ここまで) (削除) 23 (削除ここまで) 22 bytes
,Ṣ↻s2f{h∈" -"&t.∧Ạụ∋}s
(-2 bytes thanks to @Fatalize.)
,Ṣ↻ % prepend a space to input
s2f % get all substrings of length 2 from that, to get prefix-character pairs
{ }s % 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
-
\$\begingroup\$ You can use
Ṣinstead of" "to save two bytes \$\endgroup\$Fatalize– Fatalize2018年07月30日 06:41:02 +00:00Commented Jul 30, 2018 at 6:41
-
\$\begingroup\$ Since you're using v2, I think you can change
"(^| |-)%A"to/^| |-)\A/to save a byte \$\endgroup\$ETHproductions– ETHproductions2017年07月21日 19:51:16 +00:00Commented Jul 21, 2017 at 19:51 -
1\$\begingroup\$
mf\A->mÌto save 2 bytes. \$\endgroup\$Shaggy– Shaggy2019年01月04日 15:55:49 +00:00Commented Jan 4, 2019 at 15:55
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 moduleFoundationthat is vital forzip(), the main piece of this code.func f(s:[String]){...}- Creates a function with a parameters, that is a list of Strings, representing the characters of the input.for i in zip(s,[" "]+s){...}- Iterates withithrough 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.
-
\$\begingroup\$ -5 with
import UIKitinstead ofimport Foundation. \$\endgroup\$Cœur– Cœur2019年07月18日 13:45:16 +00:00Commented Jul 18, 2019 at 13:45
PowerShell, 43 bytes
''+($args|sls '(?<=^| |-)[A-Z]'-a -ca|% m*)
Unrolled:
''+($args|select-string '(?<=^| |-)[A-Z]' -allmatches -caseSensitive|% matches)
Python 3, 67 bytes
lambda x:[c[0]for c in x.replace("-"," ").split()if c[0].isupper()]
Python 3, (削除) 73 (削除ここまで) 70 bytes
lambda n:[n[x]for x in range(len(n))if'@'<n[x]<'['and(' '+n)[x]in' -']
Explanation
lambda n:- Creates an anonymous lambda-function with a String parametern.n[x]- Gets the character ofnat indexx.for x in range(len(n))- Iterates from0to the length ofn, naming the variablex.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 andn.
-
2\$\begingroup\$ Is it bad that I read that as
i supper, and I have no idea why? \$\endgroup\$TheLethalCoder– TheLethalCoder2017年07月21日 13:22:13 +00:00Commented Jul 21, 2017 at 13:22 -
\$\begingroup\$ @TheLethalCoder It's
.isupper(), I have no idea what you read :p \$\endgroup\$Mr. Xcoder– Mr. Xcoder2017年07月21日 13:23:10 +00:00Commented Jul 21, 2017 at 13:23
JavaScript (SpiderMonkey), 62 bytes
n=s=>(""+s.match(/([ -]|^)[A-Z]/g)).replace(/[ \-,]|null/g,"")
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
-
\$\begingroup\$
^| |-might be a shorter test? \$\endgroup\$Neil– Neil2017年07月21日 15:43:12 +00:00Commented Jul 21, 2017 at 15:43 -
\$\begingroup\$ @Neil that works here, thanks. Missed it because it doesn't work in Python \$\endgroup\$Chris H– Chris H2017年07月21日 15:58:50 +00:00Commented Jul 21, 2017 at 15:58
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.
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
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
-
\$\begingroup\$ Would it be possible to completely remove
#include<string>and assume the argumentsis astd::string? \$\endgroup\$Adalynn– Adalynn2017年10月05日 17:01:02 +00:00Commented Oct 5, 2017 at 17:01
Lua, (削除) 79 (削除ここまで) 75 bytes
for i=1,#t do for i in(" "..t[i]):gmatch"[%-| ]%u"do print(i:sub(2))end end
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)
Pyth, 12 bytes
Created one year after the initial answer.
rI#1hMcXQ\-d
Pyth, 21 bytes
Initial answer.
:+dQ"(?<=[ -])[A-Z]"1
-
\$\begingroup\$
-|is one byte less than[ -]\$\endgroup\$ATaco– ATaco2017年07月23日 23:45:24 +00:00Commented Jul 23, 2017 at 23:45 -
\$\begingroup\$ @ATaco That does not seem to work \$\endgroup\$Mr. Xcoder– Mr. Xcoder2017年07月24日 03:47:19 +00:00Commented Jul 24, 2017 at 3:47
[email protected]. \$\endgroup\$