18
\$\begingroup\$

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 so shortest code in bytes for each language wins.


  1. Thanks to @JonathanAllan for pointing out two mistakes.
asked May 12, 2018 at 14:15
\$\endgroup\$
16
  • 8
    \$\begingroup\$ Tips when creating test cases: Make each one cover at least one corner case. All your test cases are basically identical (maybe except the one with 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\$ Commented May 12, 2018 at 16:11
  • \$\begingroup\$ You're missing a delimiter in the last test case - there should be a ! there. I would edit it myself, but there's not enough characters for me to do it. \$\endgroup\$ Commented May 13, 2018 at 13:11
  • 1
    \$\begingroup\$ I've downvoted this due to the multiple changes to the spec. On a sidenote, you need to make mention a lot sooner than the last test case that the string may contain 2 or more consecutive "separators" and that we are not guaranteed that a letter will always follow a "separator". \$\endgroup\$ Commented May 13, 2018 at 15:55
  • 3
    \$\begingroup\$ I looked it up: Stewie didn't suggest any test cases, but he asked whether the first or last character could be a separator and whether there could be consecutive separators. In the future, please consider using the sandbox to get all these details sorted out before going live. It's frustrating to get your answer invalidated because of changes in the specification. The most surprising of all is the restriction to take the character as input, even if the program doesn't need it. That makes no sense at all. \$\endgroup\$ Commented May 13, 2018 at 16:22
  • 1
    \$\begingroup\$ Can we have a test-case with separator ., I can imagine some string splitting functions struggling with that one. \$\endgroup\$ Commented May 14, 2018 at 8:15

33 Answers 33

1
2
9
\$\begingroup\$

Python 3, 63 bytes

lambda s,c:''.join(map(min,s,s[0]+s.title()[1:])).replace(c,'')

Try it online!

answered May 12, 2018 at 18:31
\$\endgroup\$
6
\$\begingroup\$

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;}

Try it online!

answered May 12, 2018 at 15:00
\$\endgroup\$
2
  • \$\begingroup\$ Suggest *s==c?*++s&=95:0; instead of if(*s==c)*++s&=95; \$\endgroup\$ Commented Dec 7, 2018 at 20:44
  • 1
    \$\begingroup\$ 48 bytes \$\endgroup\$ Commented Oct 7, 2024 at 16:35
5
\$\begingroup\$

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())

Try it online!

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()
answered May 12, 2018 at 14:24
\$\endgroup\$
11
  • \$\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\$ Commented May 13, 2018 at 4:20
  • \$\begingroup\$ 50 bytes. Or 47 if you don't bother taking the second input, which is irrelevant. \$\endgroup\$ Commented May 13, 2018 at 15:06
  • 1
    \$\begingroup\$ @Shaggy Thanks! I've added it as a separate version, since the new rules are quite different from the original ones. \$\endgroup\$ Commented May 13, 2018 at 15:20
  • 1
    \$\begingroup\$ fail !prob!!lem!s!Olved!! \$\endgroup\$ Commented 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\$ Commented May 13, 2018 at 15:53
3
\$\begingroup\$

APL (Dyalog Classic), 22 bytes

{⍵~⍨1(819⌶@(⍵= ̄1⌽⊢))⍺}

Try it online!

answered May 12, 2018 at 15:35
\$\endgroup\$
2
  • \$\begingroup\$ Why Dyalog Classic for this answer? \$\endgroup\$ Commented 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\$ Commented Sep 11, 2020 at 11:38
3
\$\begingroup\$

Perl 6 -p, 19 bytes

s:g[<:!L>(.)]=0ドル.uc

Try it online!

answered May 12, 2018 at 15:38
\$\endgroup\$
3
\$\begingroup\$

sed 4.2.2 (-r), 21

s/[^a-z]+(.)?/\u1円/gi

I tried \W instead of [^a-z], but unfortunately that doesn't match _.

Try it online!

answered May 12, 2018 at 15:20
\$\endgroup\$
2
  • \$\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\$ Commented May 12, 2018 at 16:12
  • \$\begingroup\$ @Mr.Xcoder Sounds good - thanks! \$\endgroup\$ Commented May 12, 2018 at 16:14
3
\$\begingroup\$

Jelly, 8 bytes

Œt81¦«8ḟ

Try it online!

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.
answered May 12, 2018 at 15:40
\$\endgroup\$
3
\$\begingroup\$

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){:}];

Try it online!

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

answered May 12, 2018 at 16:03
\$\endgroup\$
0
3
\$\begingroup\$

V, 6 (削除) 7 (削除ここまで) bytes

1 byte saved by not using argument

ÓÁˆ/õ±

Try it online!

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円

answered May 12, 2018 at 16:44
\$\endgroup\$
2
  • \$\begingroup\$ Doesn't work for input where c is a special regex character \$\endgroup\$ Commented May 13, 2018 at 4:24
  • 1
    \$\begingroup\$ @ConorO'Brien Fixed, and thanks to this I found a shorter solution :D \$\endgroup\$ Commented May 13, 2018 at 9:06
3
\$\begingroup\$

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.

answered May 12, 2018 at 17:56
\$\endgroup\$
1
  • \$\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\$ Commented May 13, 2018 at 9:23
2
\$\begingroup\$

Röda, (削除) 57 (削除ここまで) 54 bytes

-3 bytes thanks to Cows quack

{(_/`\Q$_`)|{pull;[upperCase(_[:1]),_1[1:]]if[#_1>0]}}

Try it online!

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 */
 }
}
answered May 12, 2018 at 17:29
\$\endgroup\$
1
  • \$\begingroup\$ You can leave out the \E from the regex, and _[0:1]_[:1] \$\endgroup\$ Commented May 12, 2018 at 17:49
2
\$\begingroup\$

Scala, 83 bytes

def f(s:String)={val w=s.split("[^a-zA-Z]");w(0)+w.tail.map(_.capitalize).mkString}

Try it online!

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
} //
answered May 12, 2018 at 14:51
\$\endgroup\$
0
1
\$\begingroup\$

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

Try it online!

answered May 12, 2018 at 19:07
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 9 bytes

¡ćsvyćusJ

Try it online!

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
answered May 13, 2018 at 14:36
\$\endgroup\$
0
1
\$\begingroup\$

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

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You can remove {and } from the for loop, it will only treat the next statement as body of the condition. \$\endgroup\$ Commented 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\$ Commented May 14, 2018 at 10:15
1
\$\begingroup\$

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)

enter image description here

answered Sep 11, 2020 at 8:18
\$\endgroup\$
1
\$\begingroup\$

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)

Try it online!

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)

Try it online!

answered Sep 11, 2020 at 7:41
\$\endgroup\$
7
  • \$\begingroup\$ Your TIO link shows that this doesn't work for the last test case... \$\endgroup\$ Commented Sep 11, 2020 at 8:47
  • \$\begingroup\$ ...but you can fix it for 48 bytes... \$\endgroup\$ Commented 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\$ Commented 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\$ Commented 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\$ Commented Sep 11, 2020 at 10:07
1
\$\begingroup\$

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

answered Apr 21, 2021 at 8:08
\$\endgroup\$
1
\$\begingroup\$

Vyxal, 5 bytes

/ḣǐJṅ

Try it Online!

answered Apr 21, 2021 at 8:19
\$\endgroup\$
1
1
\$\begingroup\$

Wolfram Language (Mathematica), (削除) 45 (削除ここまで) 40 bytes

StringReplace[#..~~c_|"":>Capitalize@c]&

Try it online!

Input [c][s].

answered Sep 11, 2020 at 22:39
\$\endgroup\$
1
\$\begingroup\$

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)

Try it online!

Not the shortest, but a different (recursive) solution

answered Oct 7, 2024 at 11:53
\$\endgroup\$
0
\$\begingroup\$

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.

answered May 13, 2018 at 9:17
\$\endgroup\$
0
\$\begingroup\$

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))}

Try it online!

answered May 13, 2018 at 13:15
\$\endgroup\$
0
\$\begingroup\$

Husk, 10 bytes

ΣΓ·:mΓo:ax

Try it online!

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"
answered May 13, 2018 at 15:33
\$\endgroup\$
0
\$\begingroup\$

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

Try it online!

answered May 13, 2018 at 19:10
\$\endgroup\$
0
\$\begingroup\$

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;}

Try it online.

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
answered May 14, 2018 at 7:31
\$\endgroup\$
0
\$\begingroup\$

R, 87 bytes

g<-function(s,x,z=strsplit(s,x,T)[[1]])cat(z[1],capwords(z[-1]),sep="")
example(chartr)

Try it online!

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.

answered May 13, 2018 at 1:22
\$\endgroup\$
0
0
\$\begingroup\$

Stax, 11 bytes

óKo{cplòüö\

Run and debug it

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

answered May 14, 2018 at 15:36
\$\endgroup\$
0
\$\begingroup\$

Ruby -pl, 36 bytes

$_.gsub!(/[^a-z]+(.|$)/i){1ドル.upcase}

Try it online!

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.

answered May 14, 2018 at 17:25
\$\endgroup\$
0
\$\begingroup\$

Python 3, 77 bytes

o=[]
for x in s.split(c): o.append(chr(ord(x[0])-32)+x[1:])
print(''.join(o))

Try it online!

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

answered Jun 6, 2018 at 9:39
\$\endgroup\$
6
  • \$\begingroup\$ What is s supposed to be ? \$\endgroup\$ Commented Jun 6, 2018 at 9:52
  • \$\begingroup\$ @MuhammadSalman A string s and a character c. \$\endgroup\$ Commented 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\$ Commented 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\$ Commented Jun 6, 2018 at 9:57
  • \$\begingroup\$ @MuhammadSalman here \$\endgroup\$ Commented Jun 6, 2018 at 10:00
1
2

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.