Your task is to write a program that performs case conversion from plain text, and other case formats, into one of the specified formats below. Inputs will be either plain lowercase text, or one of the detailed cases below. You must remove non-alphabetic characters except (space), _ (underscore) and - (hyphen), then split the string into words by the locations of /_/- and places where two adjacent characters have different cases (e.g. bA). Then change the capitalization of each word and join the words on some delimiting character. The specifics of capitalization and delimiter depend on the case conversion chosen.

Your program must be a polyglot in at least two different languages. For example, running your code in Python 2 transforms input to snake_case, running it in JavaScript transforms to kebab-case, Ruby transforms to PascalCase and 05AB1E transforms to camelCase.


The following case conversions can be completed:

Case Capitalization Delimiter
camelCase First word should be all lowercase; the rest should be all lowercase except for the first letter, which should be uppercase. None
PascalCase The first letter of each word should be uppercase, the rest lowercase. None
snake_case Words should be all lowercase. _
UPPER_SNAKE_CASE Words should be all uppercase. _
kebab-case Words should be all lowercase. -


this is a test         thisIsATest
camelCaseTest          camelCaseTest
PascalCaseTest         pascalCaseTest
snake_case_test        snakeCaseTest
kebab-case-test        kebabCaseTest
testing!!one!!!1!!!    testingOne1
aBCDef                 aBCDef
ABCDef                 aBCDef
a_b_c_def              aBCDef
a-b-c-def              aBCDef

Try it online!


this is a test         ThisIsATest
camelCaseTest          CamelCaseTest
PascalCaseTest         PascalCaseTest
snake_case_test        SnakeCaseTest
kebab-case-test        KebabCaseTest
testing!!one!!!1!!!    TestingOne1
aBCDef                 ABCDef
ABCDef                 ABCDef
a_b_c_def              ABCDef
a-b-c-def              ABCDef

Try it online!


this is a test         this_is_a_test
camelCaseTest          camel_case_test
PascalCaseTest         pascal_case_test
snake_case_test        snake_case_test
kebab-case-test        kebab_case_test
testing!!one!!!1!!!    testing_one_1
aBCDef                 a_b_c_def
ABCDef                 a_b_c_def
a_b_c_def              a_b_c_def
a-b-c-def              a_b_c_def

Try it online!


this is a test        THIS_IS_A_TEST
camelCaseTest         CAMEL_CASE_TEST
PascalCaseTest        PASCAL_CASE_TEST
snake_case_test       SNAKE_CASE_TEST
kebab-case-test       KEBAB_CASE_TEST
testing!!one!!!1!!!   TESTING_ONE_1
aBCDef                A_B_C_DEF
ABCDef                A_B_C_DEF
a_b_c_def             A_B_C_DEF
a-b-c-def             A_B_C_DEF

Try it online!


this is a test         this-is-a-test
camelCaseTest          camel-case-test
PascalCaseTest         pascal-case-test
snake_case_test        snake-case-test
kebab-case-test        kebab-case-test
testing!!one!!!1!!!    testing-one-1
aBCDef                 a-b-c-def
ABCDef                 a-b-c-def
a_b_c_def              a-b-c-def
a-b-c-def              a-b-c-def

Try it online!


  • Your code should produce the same output as the linked examples.
  • Entries with the most conversions in each language win, with code length being a tie-breaker.
  • \$\begingroup\$ Related. Sandbox post. \$\endgroup\$ Aug 2 at 11:46
  • 2
    \$\begingroup\$ I like SCREAMING_CASE as a name for this one \$\endgroup\$
    – Jonah
    Aug 2 at 23:56
  • \$\begingroup\$ "You must remove non-alphabetic characters except (space), _ (underscore) and - (hyphen), then split the string into words by the locations of /_/- and places where two adjacent characters have different cases (e.g. bA). Then change the capitalization of each word and join the words on some delimiting character. " May I implement my conversion in different way as long as it yield same output as the algorithm described here? \$\endgroup\$
    – tsh
    Aug 3 at 3:04
  • \$\begingroup\$ @tsh absolutely, the explicit process is there for clarity only \$\endgroup\$ Aug 3 at 6:20
  • \$\begingroup\$ "Inputs will be either plain lowercase text, or one of the detailed cases below." Test case Testing!!one!!!1!!! doesn't seem to apply to this? \$\endgroup\$ Aug 3 at 6:29

2 Answers 2


Java, Retina, 05AB1E, 05AB1E (legacy), 2sable, 166 characters

s->s.replaceAll("[A-Z]","-$0").toLowerCase().replaceAll(" |_","-").replaceAll("^-","")/*


Try it online in Java: kebab-case
Try it online in Retina: snake_case
Try it online in 05AB1E: PascalCase
Try it online in 05AB1E (legacy): camelCase
Try it online in 2sable: SCREAMING_SNAKE_CASE



//...                   // No-op comment
s->                     // Method with String as both parameter and return-type
  s.replaceAll(         //  Regex-replace all:
     "[A-Z]",           //   Uppercase letters
     "-$0")             //   To the same uppercase letter with a prepended "-"
   .toLowerCase()       //  Then convert it to lowercase
   .replaceAll(         //  Then regex-replace all:
     " |_",             //   Spaces or "_"
     "-")               //   To "-"
   .replaceAll("^-","") //  And remove a potential leading "-"
/*...*/                 // No-op comment
                        // No-op newline



Replace the first line to the second in the (implicit) input-string; which is basically a no-op replacement.


Prepend a _ in front of each uppercase letter.


Convert everything to lowercase.


Replace any space or - to _.


Remove a potential leading _.


No-op replacement to close the Java comment.

05AB1E / 05AB1E (legacy) / 2sable:

Let's start with a bit of history of these three versions. The development of 05AB1E started at the start of 2016 (or actually, the very first git-commit was on December 21st, 2015). This new codegolf language was being built in Python as backend. Mid 2016 2sable was branched of that current 05AB1E version (July 7th, 2016 to be exact), and the strength of 2sable in comparison to that old 05AB1E version was added: implicit inputs. Later on implicit input was also added to 05AB1E, and 2sable became obsolete and basically a forgotten version right after it was created on that day July 7th, 2016.
Then in mid-2018, a new 05AB1E version was being started, this time completely rewritten in Elixir instead of Python, with loads of new builtins added and some builtins changed or even removed.

So, let's go over the code and see what it does in each of the three versions:

/                # Divide the (implicit) input-string with itself, which is a no-op
                 # for strings
 /               # And again
'_              '# Push string "_"
  U              # Pop and store it in variable `X`
ðX:              # Replace all spaces with "_"
'-X:            '# Replace all "-" with a "_" as well
Au               # Push the uppercase alphabet
  D              # Duplicate it
   S             # Convert the copy to a list of characters
    X«           # Append "_" to each
      í          # Reverse each so "_" is prepended instead
                 # (2sable lacks prepend-builtin `ì`, hence the `«í` instead)
       ‡         # Transliterate, basically prepending a "_" before each uppercase
                 # letter in the input-string
X¡               # Then split on "_"
  õK             # Remove all empty strings, in case the input started with an
                 # uppercase letter
D                # Duplicate the current list of strings
 т               # 05AB1E / 05AB1E (legacy): push 100
                 # 2-sable: no-op
  н              # Pop and push the first character:
                 #  05AB1E / 05AB1E (legacy): pops 100, pushes 1
                 #  2-sable: pops the string: pushes its first character
   i             # If this is 1 (continue for 05AB1E / 05AB1E (legacy)):
    ™            #  Titlecase each inner string
     J           #  Join it together
      ć          #  Extract the first character
       „ul       #  Push string "ul"
          ®      #  Push -1
           d     #  05AB1E: check if it's a non-negative (>=0) integer: pop -1, push 0
                 #  05AB1E (legacy): check if it's an integer: pop -1, push 1
            è    #  Use that to index into the "ul" string
             .V  #  Execute it as 05AB1E code
                 #   05AB1E: uppercase the letter
                 #   05AB1E (legacy): lowercase the letter
               ì #  Prepend it back to the string
   ë             # Else (continue for 2sable):
    Xý           #  Join the list with "_" delimiter
      u          #  Uppercase the letters in the string
   }             # (for all three again): close the if-else statement
    q            # Exit the program, making everything after it no-ops
                 # (after which the result is output implicitly)

Minor note: ®dilëu would have been shorter than „ul®dè.V, but unfortunately 2sable doesn't deal very well with nested if-else statements.


Ruby & J, 189 bytes

NB.x rescue puts$<.read.split(/(?=[A-Z])|[^a-zA-Z]+/).map{_1.downcase.gsub(/[^a-z]/,'')}*"_"
#]exit'']echo tolower(,'-'&,)&:>/a:-.~(<@(-.-.&AlphaNum_j_)@u:;.1~1:0}<&97+.>&122)&(3&u:)(1!:1)3

Ruby (snake)

J (kebab)

These are really terrible as golfs, and I was hoping to get at least one more lang, but this was all I could manage for tonight...

  • NB. is the J comment prefix, and NB.x is valid ruby code for attempting to invoke the method x on the constant NB. It will fail since NB is undefined, but we can then just rescue that error and proceed as normal.
  • # is a ruby comment, and a J verb. It gets ignored when J runs because J executes right to left, and we exit before it gets interpreted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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