Challenge :
Given a string split at specific positions and capitalize the first character of the given word. Capitalize the first word's first char if and only if it was already capitalized
Input :
A string s and a character c.
Ouput :
The string with each occurrence of c replaced with the first char capitalized
Examples :
STRING(s) CHARACTER(c) RESULT
Hello_world _ HelloWorld
me,no,like , meNoLike
you-got-it - youGotIt
Am^I^clear ^ AmIClear
go!full!caps ! goFullCaps
weird&but&tRue & weirdButTRue
ProbleM1fixed1no 1 ProbleMFixedNo
!prob!!lem!s!Olved!! ! ProbLemSOlved
Note :
- Given input will always be valid. i.e : The first will always be a string with at least one instance of the character to replace at. The second will always will be a single character.
- The length of the input string will be greater 4.
There will be at least one occurrence of the character to split at.
The input is guaranteed to contain only letters and the separator (Thanks @Arnauld)
- Separator is anything that is not an alphabet (a-z / A-Z) (suggested by @Dennis)
Winning criteria :
This is code-golf so shortest code in bytes for each language wins.
- Thanks to @JonathanAllan for pointing out two mistakes.
33 Answers 33
C (gcc), (削除) 61 (削除ここまで) (削除) 53 (削除ここまで) 55 bytes
-8 bytes thanks to Dennis!
f(s,c)char*s;{for(;*s;putchar(*s++))if(*s==c)*++s&=95;}
-
\$\begingroup\$ Suggest
*s==c?*++s&=95:0;instead ofif(*s==c)*++s&=95;\$\endgroup\$ceilingcat– ceilingcat2018年12月07日 20:44:16 +00:00Commented Dec 7, 2018 at 20:44 -
1
JavaScript (ES6), (削除) 58 (削除ここまで) 56 bytes
Saved 2 bytes thanks to @l4m2 / @Downgoat
Takes input in currying syntax (s)(c).
s=>c=>s.replace(u=/./g,x=>u=x==c?'':u?x:x.toUpperCase())
Commented
s => c => // given s and c
s.replace(u = /./g, x => // initialize u to a RegExp; replace each character x in s with,
u = // and update u to:
x == c ? // if x is the separator:
'' // an empty string
: // else:
u ? // if u is not an empty string:
x // x unchanged
: // else:
x.toUpperCase() // x capitalized
) // end of replace()
-
\$\begingroup\$ consolation 56 bytes for
s=>c=>s.replace(RegExp(c+".","g"),m=>m[1].toUpperCase()), since it doesn't work for special regex characters \$\endgroup\$Conor O'Brien– Conor O'Brien2018年05月13日 04:20:20 +00:00Commented May 13, 2018 at 4:20 -
-
1\$\begingroup\$ @Shaggy Thanks! I've added it as a separate version, since the new rules are quite different from the original ones. \$\endgroup\$Arnauld– Arnauld2018年05月13日 15:20:42 +00:00Commented May 13, 2018 at 15:20
-
1\$\begingroup\$ fail
!prob!!lem!s!Olved!!\$\endgroup\$l4m2– l4m22018年05月13日 15:32:52 +00:00Commented May 13, 2018 at 15:32 -
\$\begingroup\$ @l4m2, that's a new test case which changes the spec yet again. A
+before the.in the RegEx will get around it. \$\endgroup\$Shaggy– Shaggy2018年05月13日 15:53:30 +00:00Commented May 13, 2018 at 15:53
-
\$\begingroup\$ Why Dyalog Classic for this answer? \$\endgroup\$Razetime– Razetime2020年09月11日 03:04:50 +00:00Commented Sep 11, 2020 at 3:04
-
1\$\begingroup\$ at the time, unicode dyalog answers were required to link to a single-byte encoding (or else scoring would default to utf8), so it was easier to post in classic dyalog \$\endgroup\$ngn– ngn2020年09月11日 11:38:30 +00:00Commented Sep 11, 2020 at 11:38
sed 4.2.2 (-r), 21
s/[^a-z]+(.)?/\u1円/gi
I tried \W instead of [^a-z], but unfortunately that doesn't match _.
-
\$\begingroup\$ By our new standards, each invocation of a flags is considered a different language, and thus your answer can be changed to
sed 4.2.2 (-r), 21 bytes. \$\endgroup\$Mr. Xcoder– Mr. Xcoder2018年05月12日 16:12:28 +00:00Commented May 12, 2018 at 16:12 -
\$\begingroup\$ @Mr.Xcoder Sounds good - thanks! \$\endgroup\$Digital Trauma– Digital Trauma2018年05月12日 16:14:03 +00:00Commented May 12, 2018 at 16:14
Jelly, 8 bytes
Œt81¦«8ḟ
How it works
Œt81¦«8ḟ Main link. Left argument: s (string). Right argument: c (character).
Œt Title case; capitalize the first character of each word.
81¦ Replace the first character of the result with the first character of s.
«8 Take the character-wise minimum of the result and s.
Note that uppercase letters have lower code points than lowercase ones.
ḟ Filterfalse; remove all occurrences of c.
Octave, (削除) 83 (削除ここまで), (削除) 66 (削除ここまで), 64 bytes
Saved 2 bytes thanks to Luis Mendo. upper instead of toupper.
@(s,c,k=upper(s(i=find(s==c)+1)))[strsplit({s(i)=k,s}{2},c){:}];
Wow, that's probably the messiest piece of Octave-code I've ever written! This uses two of the tricks posted in this tips question, namely Argument list, and cell arrays.
Explanation:
Argument list input:
@(s,c,k % An anonymous function that may take three input variables, s, c, k
% where the third argument has the default value:
k=upper(s(i=find(s==c)+1))
k is here the first character in s after each separator c, converted to upper case. The index of each capitalized character is stored in i.
Cell array body:
We create a cell array with two elements, one were we say that all i'th characters should be substituted by its counterpart in k, and the other one with s, that is now already updated. We index this using {2} so that we only get the whole, modified string back. This is fed to strsplit, which splits it into cells at the separator character. We convert it to a comma-separated list using {:}, and concatenates it back to a string using square brackets [].
Apologies if that didn't make any sense to you... It barely makes sense to me :P
V, 6 (削除) 7 (削除ここまで) bytes
1 byte saved by not using argument
ÓÁ/õ±
The program takes in the text as input and the char as an argument.
Hexdump:
00000000: d3c1 882f f5b1 .../..
This is a simple substitution. Uncompressed, it looks like the following
:s/\A(.)/\u1円/g
Perform a global substitution in which \A, a non-alphabetic character, followed by a character (.) is replaced with uppercased \u first capture group 1円
-
\$\begingroup\$ Doesn't work for input where
cis a special regex character \$\endgroup\$Conor O'Brien– Conor O'Brien2018年05月13日 04:24:07 +00:00Commented May 13, 2018 at 4:24 -
1\$\begingroup\$ @ConorO'Brien Fixed, and thanks to this I found a shorter solution :D \$\endgroup\$user41805– user418052018年05月13日 09:06:15 +00:00Commented May 13, 2018 at 9:06
Retina 0.8.2, 20 bytes
T`lLp`LL_`[\W\d_]+.?
Try it online! Takes the string only, separator optional. All non-alphabetic characters are deleted but any following alphabetic character is uppercased. Previous 34-byte version accepted arbitrary input:
T`l`L`(?=.*(.)$)1円+.
(?=.*(.)$)1円
Try it online! Link includes test suite. Assumes the input consists of the string and character concatenated together. Explanation: The first stage transliterates all characters immediately following occurrences of the end character from lower to upper case and the second stage then deletes all occurrences of the end character.
For both solutions, using a right-to-left match instead of a + also works.
-
\$\begingroup\$ Since the input is guaranteed to only contain alphabetic characters and the separator, you can use
[^a-z]instead of the lookaheads Try it online! \$\endgroup\$user41805– user418052018年05月13日 09:23:10 +00:00Commented May 13, 2018 at 9:23
Röda, (削除) 57 (削除ここまで) 54 bytes
-3 bytes thanks to Cows quack
{(_/`\Q$_`)|{pull;[upperCase(_[:1]),_1[1:]]if[#_1>0]}}
Explanation:
{
(_/`\Q$_`)| /* Pull two strings and split the first with the second */
{
pull; /* Pull one string and print it */
/* For each string _1 in the stream: */
/* If _1 is not empty: */
[ /* Print: */
upperCase(_[:1]), /* The first character capitalized */
_1[1:] /* The rest of characters */
]if[#_1>0] /* End if */
}
}
-
\$\begingroup\$ You can leave out the
\Efrom the regex, and_[0:1]→_[:1]\$\endgroup\$user41805– user418052018年05月12日 17:49:28 +00:00Commented May 12, 2018 at 17:49
Scala, 83 bytes
def f(s:String)={val w=s.split("[^a-zA-Z]");w(0)+w.tail.map(_.capitalize).mkString}
Explanation:
def f(s: String) = { // takes a String "s" as input
val w = s.split("[^a-zA-Z]"); // split on non-alpha chars
w(0) + w.tail.map(_.capitalize).mkString // upper case first letter of all words except first one and join array into a String
} //
Red, 87 bytes
func[s c][b: split s c prin b/1 foreach w next b[if w <>""[w/1: uppercase w/1 prin w]]]
05AB1E, 9 bytes
¡ćsvyćusJ
Explanation
¡ # split the string on the char
ć # extract the head of the resulting list
s # swap the head to the bottom of the stack
vy # for each string y in the rest of the list
ću # extract the head and capitalize it
s # swap it below the rest of the string
J # join everything to one string
PHP, (削除) 91 (削除ここまで) 83 bytes
$a=explode($argv[2],$argv[1]);echo array_shift($a);foreach($a as$i)echo ucfirst($i);
Run with -r. Was 2 bytes shorter using split instead of explode, but ^ test fails due to regex.
-8 thanks to Med
-
1\$\begingroup\$ You can remove
{and}from the for loop, it will only treat the next statement as body of the condition. \$\endgroup\$Med– Med2018年05月14日 10:01:33 +00:00Commented May 14, 2018 at 10:01 -
1\$\begingroup\$ You can even do the echo inside the loop:
$a=explode($argv[2],$argv[1]);echo array_shift($a);foreach($a as$i)echo ucfirst($i);\$\endgroup\$Med– Med2018年05月14日 10:15:46 +00:00Commented May 14, 2018 at 10:15
LaTeX, 97 bytes
The function
\def~#1#2{{\seq_set_split:Nnn~{#2}{#1}\seq_map_function:NN~"}}\def"{\let"\text_titlecase_first:n}
Complete document with test cases
\documentclass[preview,border=3.14]{standalone}
\ExplSyntaxOn
\catcode`\~13
\catcode`\"13
\def~#1#2{{\seq_set_split:Nnn~{#2}{#1}\seq_map_function:NN~"}}\def"{\let"\text_titlecase_first:n}
\ExplSyntaxOff
\begin{document}
~{Hello_world}_
~{me,no,like},
~{you-got-it}-
~{Am^I^clear}^
~{go!full!caps}!
~{weird&but&tRue}&
~{ProbleM1fixed1no}1
~{!prob!!lem!s!Olved!!}!
\end{document}
Results (in PDF)
R, 64 bytes
Pure regular expression solution using https://www.regular-expressions.info/replacecase.html. Unfortunately separators can be underscores so I couldn't use \w to capture letters. Improved version taking advantage of gsub's ignore.case parameter to save on [a-zA-Z]. Correction thanks to https://codegolf.stackexchange.com/users/95126/dominic-van-essen, who has a 25% shorter solution in the comments.
function(s,c)gsub('[^a-z]([a-z]?)([a-z]*)','\\U\1円\\E\2円',s,T,T)
https://codegolf.stackexchange.com/users/95126/dominic-van-essen 's solution, with an extra character removed (by using ? for optional):
R, 47 bytes
function(s,c)gsub("[^a-z]+(.)?","\\U\1円",s,T,T)
-
\$\begingroup\$ Your TIO link shows that this doesn't work for the last test case... \$\endgroup\$Dominic van Essen– Dominic van Essen2020年09月11日 08:47:04 +00:00Commented Sep 11, 2020 at 8:47
-
\$\begingroup\$ ...but you can fix it for 48 bytes... \$\endgroup\$Dominic van Essen– Dominic van Essen2020年09月11日 08:55:05 +00:00Commented Sep 11, 2020 at 8:55
-
1\$\begingroup\$ Would you like to add your (growing number of) R golfs to the Language of the month page (edit the first 'answer' there...). It's nice for other R-golfers (and would-be-R-golfers) to be able to easily find examples to learn from... \$\endgroup\$Dominic van Essen– Dominic van Essen2020年09月11日 09:00:02 +00:00Commented Sep 11, 2020 at 9:00
-
1\$\begingroup\$ Thanks for the correction @DominicvanEssen, much better than mine! I'm amused that not using the argument is still better! \$\endgroup\$Cong Chen– Cong Chen2020年09月11日 09:01:52 +00:00Commented Sep 11, 2020 at 9:01
-
1\$\begingroup\$ Well done on shaving another byte off my attempt! By the way, if you're embedding links, you can make your text more readable by using a link-label in square-brackets [ ] immediately followed by the link itself in parentheses ( ). \$\endgroup\$Dominic van Essen– Dominic van Essen2020年09月11日 10:07:54 +00:00Commented Sep 11, 2020 at 10:07
Pinecone, 314 bytes
s:String.input;p:String.input;k:IntArray:s.len;k.set:0,-1;o:"";n:1;i:0|i<s.len|i:i+1@((s.sub:i,i+1)=p?(k.set:n,i;n:n+1))k.set:n,s.len;i:1|i<n+1|i:i+1@(x:k.get:i-1;y:k.get:i;x:x+1;j:s.sub:x,y;e:1|e<256|e:e+1@((j.sub:0,1)=e.ascii?(e<96?(o:o+(e.ascii)+(j.sub:1,(j.len)))|(o:o+(e-32).ascii+(j.sub:1,(j.len))))))print:o
This was extremely fun....
-
\$\begingroup\$ Use the
sflag for 4 bytes \$\endgroup\$2021年04月21日 09:07:46 +00:00Commented Apr 21, 2021 at 9:07
Wolfram Language (Mathematica), (削除) 45 (削除ここまで) 40 bytes
StringReplace[#..~~c_|"":>Capitalize@c]&
Input [c][s].
Python 3.8 (pre-release), 65 bytes
f=lambda i,s,l=1:i and(l*i+i.upper())[:(x:=i[0]!=s)]+f(i[1:],s,x)
Not the shortest, but a different (recursive) solution
Groovy, 43 bytes, (削除) 45 bytes (削除ここまで)
s.replaceAll(/\$c(.)/){it[1].toUpperCase()}
Try it online. Test suite included excluding the last item as it lacks the separator char c.
Go, (削除) 138 (削除ここまで) (削除) 92 (削除ここまで) 87 bytes
Dropped 46 bytes thanks to @Dennis' title case idea.
func f(s,d string){p:=Split(s,d);Print(p[0]+Replace(Title(Join(p[1:]," "))," ","",-1))}
Husk, 10 bytes
ΣΓ·:mΓo:ax
Explanation
ΣΓ·:mΓ(:a)x -- example inputs: 'x' "abxbcxcdxdex"
x -- split on character: ["ab","bc","cd","de"]
Γ -- pattern match (x = head) (xs = tail) and do..
·: -- | construct list (x:xs) but with the second argument do..
m -- | | map (eg. "bc")
Γ( ) -- | | | pattern match on first character
( a) -- | | | | upper-case it
(: ) -- | | | | and join again
-- | | | : "Bc"
-- | | : ["Bc","Cd","De"]
-- : ["ab","Bc","Cd","De"]
Σ -- concatenate: "abBcCdDe"
F# (Mono), 122 bytes
let f(s:string)c=s|>Seq.mapi(fun i x->if i>0&&s.[i-1]=c then Char.ToUpper(x)else x)|>Seq.where((<>)c)|>Seq.toArray|>String
Java 10, 141 bytes
s->c->{var r=s.split("\\"+c);var r=a[0],t;for(int i=0;++i<a.length;r+=t.isEmpty()?"":(char)(t.charAt(0)&~32)+t.substring(1))t=a[i];return r;}
Explanation:
s->c->{ // Method with String and character parameters and String return-type
var r=s.split("\\"+c); // Split String by character (with potential regex char)
var r=a[0], // Result-String, starting at the first item
t; // Temp-String to reduce bytes
for(int i=0;++i<a.length;// Loop in the range [1, length_of_array)
r+= // After every iteration: append the result-String with:
t.isEmpty()? // If the current item empty:
"" // Append nothing
: // Else:
(char)(t.charAt(0)&~32)
// Capitalize the first character
+t.substring(1)) // And append the other characters as is
t=a[i]; // Set `t` to the current String-item of the array
return r;} // Return the result-String
R, 87 bytes
g<-function(s,x,z=strsplit(s,x,T)[[1]])cat(z[1],capwords(z[-1]),sep="")
example(chartr)
Uses this trick can can not be properly executed in TIO so I simulated it.
We need the T otherwise one of the test cases fails.
Stax, 11 bytes
óKo{cplòüö\
Explanation
/BsF1:/s^s|dl # Full Program, unpacked, Implicit Input
/ # Split on substrings (Split input with symbol to split on)
B # Remove first element from array. Push the tail of the array, then the removed element.
s # Swap first two elements of stack
F # Start for loop
1:/ # Split array at index; push both parts.
s^s # Swap first two elements of stack, capitalize character, swap first two elements
|dl # Get length of stack, listify that amount (entire stack), implicit output of array
There's a few parts I would really like to fix somehow. I can get it down to about 8 bytes, but it fails on the last test case>.<
Ruby -pl, 36 bytes
$_.gsub!(/[^a-z]+(.|$)/i){1ドル.upcase}
Takes only the string without second argument. Uses the block version of gsub! method because with common gsub! x,y syntax 1ドル is not readily filled with match data. |$ in regex is necessary for the test case with separator in the end.
Python 3, 77 bytes
o=[]
for x in s.split(c): o.append(chr(ord(x[0])-32)+x[1:])
print(''.join(o))
This assumes that the string is ASCII encoded and assumes that s and c are preloaded variables containing the input.
for x in s.split(x) #loop through items in the string s split by x
o.append( #add the following to c
chr( #turn the following number into a character
ord( #turn the following character into a number
x[0] #the first character in string x
)-32 #subtract 32 from this number
+x[1:] #add everything past and including the second character in string x
This solution works on the fact that in ASCII encoding, lowercase letters are positioned 32 entries after capitalised letters
Edit: i just realised that this also capitalises the first character in the string, which it shouldn't. but i'm quite proud of my nonsense, so i'll leave this up if that's allowed
-
\$\begingroup\$ What is
ssupposed to be ? \$\endgroup\$Muhammad Salman– Muhammad Salman2018年06月06日 09:52:07 +00:00Commented Jun 6, 2018 at 9:52 -
\$\begingroup\$ @MuhammadSalman
A string s and a character c.\$\endgroup\$Davin Miler– Davin Miler2018年06月06日 09:53:17 +00:00Commented Jun 6, 2018 at 9:53 -
\$\begingroup\$ Lovely, make it work, Go here and see if it works or not : TIO. When it does tell me ? \$\endgroup\$Muhammad Salman– Muhammad Salman2018年06月06日 09:55:27 +00:00Commented Jun 6, 2018 at 9:55
-
\$\begingroup\$ oops! i just realised i made a mistake when changing the variable names, c=[] is supposed to be any other variable \$\endgroup\$Davin Miler– Davin Miler2018年06月06日 09:57:47 +00:00Commented Jun 6, 2018 at 9:57
-
\$\begingroup\$ @MuhammadSalman here \$\endgroup\$Davin Miler– Davin Miler2018年06月06日 10:00:27 +00:00Commented Jun 6, 2018 at 10:00
1). Try to think about how solutions might fail, and make a test case for such situations. Some examples: Letters as separators, the separator being the last character, consecutive separators and so on. There's no need to have many test cases that doesn't test different things. \$\endgroup\$., I can imagine some string splitting functions struggling with that one. \$\endgroup\$