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 :

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)

  • You are required to take both inputs and not the string alone.
  • 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.
  • 5
    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. – Stewie Griffin 20 hours ago

15 Answers 15

JavaScript (ES6), 58 bytes

Takes input in currying syntax (s)(c).

s=>c=>s.replace(u=/./g,x=>u=x==c?'':u<1?x.toUpperCase():x)

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 < 1 ?            //     if u is an empty string:
          x.toUpperCase()  //       x capitalized
        :                  //     else:
          x                //       x unchanged
  )                        // end of replace()

Given that:

  • r < 1 === false if r is a RegExp
  • c < 1 === false if c is a printable ASCII character other than space or 0
  • "" < 1 === true
  • Thanks for adding the explanation – Muhammad Salman 21 hours ago
  • consolation 56 bytes for s=>c=>s.replace(RegExp(c+".","g"),m=>m[1].toUpperCase()), since it doesn't work for special regex characters – Conor O'Brien 8 hours ago

Perl 6 -p, 19 bytes

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

Try it online!

sed 4.2.2 (-r), 21

s/[^a-z]+(.)?/\u\1/gi

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

Try it online!

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

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!

Python 3, 63 bytes

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

Try it online!

APL (Dyalog Classic), 22 bytes

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

Try it online!

Jelly, 8 bytes

Œt⁸1¦«⁸ḟ

Try it online!

How it works

Œt⁸1¦«⁸ḟ  Main link. Left argument: s (string). Right argument: c (character).

Œt        Title case; capitalize the first character of each word.
  ⁸1¦     Replace the first character of the result with the first character of s.
     «⁸   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.

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 */
  }
}
  • You can leave out the \E from the regex, and _[0:1]_[:1] – Cows quack 18 hours ago

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(.)/\u\1/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

  • Doesn't work for input where c is a special regex character – Conor O'Brien 8 hours ago
  • @ConorO'Brien Fixed, and thanks to this I found a shorter solution :D – Cows quack 3 hours ago

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!

Scala, 89 bytes

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

Try it online!

Explanation:

def f(s: String, c: Any) = {               // takes a String "s" and a Char 'c' in input
  val w = s.split("[^a-zA-Z]");             // split on punctuation
  w(0) + w.tail.map(_.capitalize).mkString  // upper case first letter of all words except first one and join array into a String
}                                           //
  • You need to take c as input – ASCII-only 21 hours ago
  • Seems like the problem can be solved without; at least based on the test cases. – Xavier Guihot 21 hours ago
  • @MuhammadSalman IMO you are still required to take c as input, the problem with c being able to be ignored is a problem with bad testcases – ASCII-only 20 hours ago
  • Please add a test case forcing the use of this otherwise non-necessary parameter. And please apply the same warning to other answers not using it as well. – Xavier Guihot 20 hours ago

Retina 0.8.2, 34 bytes

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. Using a right-to-left match instead of a + also works.

  • @MuhammadSalman Two. The last character on each line is the second input. – Dennis 18 hours ago
  • 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! – Cows quack 3 hours ago

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.

Groovy, 45 bytes, 43 bytes

s.replaceAll(/\$c(.)/){it[1].toUpperCase()}

Try it online. Test suite included excluding the last item as it lacks the separator char c.

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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