25
\$\begingroup\$

There are a bunch of different casing conventions, like camelCase, PascalCase, snake_case etc. It's annoying juggling all of these, so instead of choosing one like a sensible person, why not cursedly mix all of them together?

Your challenge is to, given a list of words (only containing lowercase letters), convert them to backwardS_hybriD-snakE_kebaB-cameL_case. To do so:

  • The words are joined by alternating underscores and hyphens, starting with underscores.
  • Capitalise the last letter of every word but the last.

This is , shortest wins!

Testcases

These are formatted as space-separated words

hello world -> hellO_world
beans -> beans
one two three four -> onE_twO-threE_four
backwards hybrid snake kebab camel case -> backwardS_hybriD-snakE_kebaB-cameL_case
test three words -> tesT_threE-words
o n e l e t t e r -> O_N-E_L-E_T-T_E-r
\$\endgroup\$
8
  • \$\begingroup\$ Can we take the words as an underscore-delimited string? \$\endgroup\$
    – Adám
    Jun 20 at 22:27
  • 8
    \$\begingroup\$ @Adám I'm going to say no to that one as it's too similar to the output. \$\endgroup\$
    – emanresu A
    Jun 20 at 22:31
  • 2
    \$\begingroup\$ There are so many casing conventions... So I choose to use CJK characters for a variable name. \$\endgroup\$
    – tsh
    Jun 21 at 2:56
  • 1
    \$\begingroup\$ mmmm, snake kebab \$\endgroup\$ Jun 21 at 12:53
  • 1
    \$\begingroup\$ @Arnauld That sounds reasonable, and I think it's in the standard I/O rules, so sure. \$\endgroup\$
    – emanresu A
    Jun 21 at 22:16

24 Answers 24

13
\$\begingroup\$

Python, 72 bytes

lambda s:re.sub(" (.*?) ",r"_\1-",s+"x ")[::-1].title()[:1:-1]
import re

Attempt This Online!

How?

Uses regular expression to substitute pairs of spaces. To make sure every space is handled the auxiliary string "x " is appended. The result is reversed, title cased and reversed back. The auxiliary string (which has absorbed one unwanted title casing) is removed.

\$\endgroup\$
9
\$\begingroup\$

JavaScript (ES6), 50 bytes

Expects and returns a list of ASCII codes.

a=>a.map((c,i)=>a[i+1]^32?c^32?c:C^=114:c^32,C=45)

Try it online!

Commented

a =>              // a[] = list of ASCII codes
a.map((c, i) =>   // for each value c at position i in a[]:
  a[i + 1] ^ 32 ? //   if the next character is not a space:
    c ^ 32 ?      //     if the current character is not a space:
      c           //       leave it unchanged
    :             //     else:
      C ^= 114    //       make C switch between '-' and '_' and use it
  :               //   else:
    c ^ 32,       //     inverse the case of the current character
  C = 45          //   start with C = 45 (i.e. '-')
)                 // end of map()
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Since you're allowed take in strings as an array of characters, are you also allowed to take it in as a Buffer of characters? \$\endgroup\$ Jun 21 at 18:30
  • \$\begingroup\$ @Samathingamajig Thank you for the suggestion. The OP has confirmed that we can take/return a list of ASCII codes, which is even easier/shorter than using Buffer. \$\endgroup\$
    – Arnauld
    Jun 21 at 22:22
7
\$\begingroup\$

Retina, 13 bytes

Y`l  `L\_-`. 

Try it online! Link includes test cases. Explanation: Cyclically transliterates each space and the lower case letter before it. Since the two transliteration strings are the same length and the lower case letters appear exactly once each (via the shorthand l) they are simply transliterated to the upper case letters (L), however, there are two spaces in the transliteration string so they get alternately transliterated to _ (which needs to be escaped in a transliteration) and - (which fortunately doesn't need to be escaped at the end of a string.)

The best I could do in Retina 0.8.2 was 23 bytes:

T`l `L\_`. 
(_.+?)_
$1-

Try it online! Link includes test cases. Explanation: Since Retina doesn't have cyclic transliteration I just transliterate all of the spaces to _s and then fix up alternate _s to -s afterwards (which has to be done longhand as Retina 0.8.2 doesn't have step limits either).

\$\endgroup\$
7
\$\begingroup\$

JavaScript, 52 bytes

-3 bytes by emanresu A; -2 bytes by Arnauld.

s=>s.replace(/. /g,c=>c[0].toUpperCase()+'-_'[s^=1])

Try it online!

\$\endgroup\$
3
5
\$\begingroup\$

Vyxal s, 12 bytes

ṫ$RǐR₅‛_-ẎYp

Try it Online!

-5 bytes thanks to emanresuA

How?

ṫ$RǐR₅‛_-ẎYp
ṫ            # Tail extract, push a[:-1] and a[-1]
 $           # Swap
  R          # Reverse each
   ǐ         # Capitalize first letter of each
    R        # Reverse each
     ₅       # Push length without popping
      ‛_-    # Push "_-"
         Ẏ   # Extend this string to the length
          Y  # Interleave the list of words and each character of this string together
           p # Append the last item of the input (pushed earlier by tail extract) to this list
             # s flag joins this list to a string
\$\endgroup\$
1
  • \$\begingroup\$ 12 \$\endgroup\$
    – emanresu A
    Jun 20 at 22:34
5
\$\begingroup\$

APL (Dyalog Extended), 25 bytes

Anonymous tacit prefix function. Takes list of words.

1⌊⍢⊃⍤↓⍢⌽∘∊⌈⍢⊃⍢⌽¨,¨'_-'⍴⍨≢

Try it online!

 tally of words

'_-'⍴⍨ use that to cyclically reshape this string

 concatenate each of those to each of the following:

 …¨ on each word:

  …⍢⌽ while reversed (reverse back again when done):

   …⍢⊃ while the first character is extracted (put it back again when done):

     uppercase

∘∊enlist (flatten), and then:

 …⍢⌽ while reversed (reverse back again when done):

  1⍤↓ drop the first character, and then:

   …⍢⊃ while the first character is extracted (put it back again when done):

     lowercase

\$\endgroup\$
4
\$\begingroup\$

Pyth, 16 bytes

ts.e+@"-_"k_r_b3

Try it online!

\$\endgroup\$
4
\$\begingroup\$

05AB1E, 13 bytes

í™í`l)„_-ÞøS¨

Input as a list of words; output as a list of characters.

Try it online or verify all test cases.

Explanation:

í             # Reverse each word in the (implicit) input-list
 ™            # Titlecase each reversed word
  í           # Reverse each back
   `          # Pop the list, and push all words separated to the stack
    l         # Lowercase the last/top one
     )        # Wrap the stack back into a list
      „_-     # Push string "_-"
         Þ    # Cycle it indefinitely: ["_","-","_","-","_","-",...]
          ø   # Create pairs of the two lists, ignoring trailing items of the
              # longer (in this case infinite) list
           S  # Convert this list of pairs to a flattened list of characters
            ¨ # Remove the trailing "_"/"-"
              # (after which the result is output implicitly)
\$\endgroup\$
3
\$\begingroup\$

Python, 86 80 bytes

lambda s,i=0:"".join("_-"[i:=~i]+w.title()for w in s[::-1].split())[:1:-1]+s[-1]

Attempt This Online!

-6 bytes thanks to @xnor

\$\endgroup\$
3
  • 1
    \$\begingroup\$ It looks like (i:=i<1) can be i:=~i. The current version of Python has improved parsing so that the parens aren't required there. \$\endgroup\$
    – xnor
    Jun 20 at 22:12
  • \$\begingroup\$ Oh that's a good improvement, I should probably update Python on my PC... \$\endgroup\$
    – jezza_99
    Jun 20 at 22:19
  • 1
    \$\begingroup\$ Saving a few bytes with .title() \$\endgroup\$
    – xnor
    Jun 20 at 22:23
3
\$\begingroup\$

Charcoal, 24 bytes

⭆θ⎇⁼ §θ⊕κ↥ι⎇⁼ ι§_-№…θκ ι

Try it online! Link is to verbose version of code. Explanation: Similar approach to @Arnauld's JavaScript answer.

 θ                          Input string
⭆                           Map over characters and join
  ⎇⁼ §θ⊕κ                   If next character is a space then
         ↥ι                 Current character uppercased
           ⎇⁼ ι             Else if current character is a space then
               §_-          Literal string `_-` cyclically indexed by
                  №…θκ      Number of spaces in current prefix
                       ι    Else current character
                            Implicitly print

I also tried an approach based on splitting and joining but I wasn't able to get it below 26 bytes.

\$\endgroup\$
3
  • \$\begingroup\$ Since the specification says "given a list of words", might you be able to take in a pre-split list as input in order to shorten the splitting and joining approach? \$\endgroup\$ Jun 21 at 2:24
  • \$\begingroup\$ @DanielSchepler Well, I guess it would get me to the same byte-count, so it could add it as an alternative approach in that case. Assuming I can remember what I did.... \$\endgroup\$
    – Neil
    Jun 21 at 8:11
  • \$\begingroup\$ @DanielSchepler Unfortunately because I had reversed the string before splitting to save me a byte, taking a list as input is still 25 bytes. \$\endgroup\$
    – Neil
    Jun 21 at 9:18
3
\$\begingroup\$

brev, 161 150 bytes

(fn(strse x (: word(neg-look-ahead eos))(as-list(fn `(,@(butlast x) ,(char-upcase(last x)))))(: ($ word)" "($ word)" ")(conc(m 1)"_"(m 2)"-")'" ""_"))

325 with white space and test cases added:

(map
 (fn (strse x (: word (neg-look-ahead eos))
            (as-list (fn `(,@(butlast x) ,(char-upcase (last x)))))
        (: ($ word) " " ($ word) " ")
        (conc (m 1) "_" (m 2) "-")
        '" " "_"))
 '("hello world"
   "beans"
   "one two three four"
   "backwards hybrid snake kebab camel case"
   "test three words"
   "o n e l e t t e r"))
\$\endgroup\$
3
\$\begingroup\$

Python 3, 165 bytes

This is my first time having a go at this, so my answer is not gonna be great, but I found this really fun

lambda w:"".join([b if not i%2 else b[1:-1] for i,b in enumerate("_/-".join([s[::-1].title()[::-1] for s in w[:-1]]+[w[-1]]).split("/"))])+w[-1][::-1][:(len(w)+1)%2]
\$\endgroup\$
1
  • \$\begingroup\$ Welcome to Code Golf, and nice first answer! You can remove the space between ] and for. \$\endgroup\$
    – emanresu A
    Jun 24 at 20:04
2
\$\begingroup\$

QuadR 2g, 37 30 29 bytes

Takes space-separated words.

(\S) 
_(.*)(\S)_
\u1_
_\1\u2-

Try it online!

PCRE Replace as follows, 2 times, with non-greedy patterns:

Target Replacement
(\S)  non-space followed by space \u1_ uppercased non-space followed by underscore
(.*?)(\S)_ any run of characters followed by a non-space and an underscore _\1\u2- an underscore, the run, the uppercased non-space, an underscore
\$\endgroup\$
2
\$\begingroup\$

MathGolf, 19 bytes

mxδmxhû_-*▒^\£<─~;!

Input as a list of words.

Try it online.

Explanation:

mx                  # Reverse each words in the (implicit) input-list
  δ                 # Titlecase each word
   mx               # Reverse each word back
     h              # Push the length of the list (without popping)
      û_-           # Push string "_-"
         *          # Repeat it the length amount of times
          ▒         # Convert it to a list ["_","-","_","-",...]
           ^        # Zip the two lists together, creating pairs
                    # (including trailing ["_"],["-"] items) 
            \       # Swap to get the input-list again
             £      # Pop and push its length
              <     # Only leave that many items (to only keep the pairs, and
                    # removing the trailing ["_"],["-"] items)
               ─    # Flatten this list of pairs
                ~   # Dump all strings separated to the stack
                 ;  # Discard the top ("_"/"-") one
                  ! # Lowercase the last/top word
                    # (implicitly join and output the entire stack)
\$\endgroup\$
2
\$\begingroup\$

Factor, 89 84 75 bytes

[ unclip [ odd? "-""_"? rot 1 cut* >upper append -rot glue ] reduce-index ]

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Python 3, 95 bytes

Honestly not a great submission, but I can't figure out a way to make it any smaller with this approach.

lambda l:''.join('-_'[i%2]+w[:-1]+(w[-1].upper(),w[-1])[i>len(l)-2]for i,w in enumerate(l))[1:]

Try it online!

\$\endgroup\$
2
\$\begingroup\$

C (gcc), 109 91 bytes

-18 bytes thanks to @ceilingcat

main(c,v)char**v;{for(;1[++v];c=!c)strlen(*v)[*v-1]-=32,printf(c?"%s_":"%s-",*v);puts(*v);}

Try it online!

\$\endgroup\$
0
1
\$\begingroup\$

BQN, 30 bytes

1↓·∾≠⊸⥊⟜"-_"∾¨-⟜32⌾⊏⌾⌽¨⌾(¯1⊸↓)

Try it here!

Explanation

  • ...¨⌾(¯1⊸↓) for each non-last word of the input...
    • -⟜32⌾⊏⌾⌽ uppercase last letter (literally by reversing and subtracting 32 from the first char)
  • ≠⊸⥊⟜"-_"∾¨ couple each word with alternations of - and _
  • 1↓·∾ join and drop first character
\$\endgroup\$
1
\$\begingroup\$

Zsh, 61 bytes

g()<<<${${4+${3%?}${3[-1]:u}$1`g $2 $1 ${@:4}`}:-$3}
g _ - $@

Try it online!

Recursive solution:

g() # define function g (braces optional since body is one line)
    <<<${${4+${3%?}${3[-1]:u}$1`g $2 $1 ${@:4}`}:-$3}
#        ${4+                                  }      # if $4 is set, substitute
#            ${3%?}                                   #   $3, remove last character
#                  ${3[-1]:u}                         #   upper last character of $3
#                            $1                       #   $1 (either _ or -)
#                              `g $2 $1 ${@:4}`       #   recurse, swapping _ and -
#      ${${                                   }:-$3}  # else substitute $3 unchanged
#   <<<                                               # print
g _ - $@   # seed initial arguments
\$\endgroup\$
1
\$\begingroup\$

Ly, 25 37 bytes

i0"_-"rsp[' =:' *lf-o[Ifprfr0]psp]>lo

Try it online!

Revised code... I didn't read the rule saying space has to be translated to - and _ alternating.

i                                     - read input as codepoints
 0"_-"                                - push "0" and delimiters
      r                               - reverse stack
       sp                             - save last and delete
         [                      p]    - loop over the 2-N chars
          ' =                         - push 0|1 from comparing curr char to " "
             :                        - duplicate result
              ' *                     - multiply result w/ " " (32)            
                 lf                   - pull prev char, flip top stack entries
                   -                  - capitalizes if the curr char is " "
                    o                 - write out char codepoint as a char
                     [      0]p       - if/then, true if " " is curr char
                      I               - copy second to bottom stack entry                fp             - pull " " forward, delete
                         rfr          - reverse bottom two entries
                               s      - stash "_" or "-"
                                  >   - switch stacks
                                   lo - load last char and print
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Your output only contains _, instead of alternating between _ and -. \$\endgroup\$ Jun 21 at 6:42
  • \$\begingroup\$ Yikes! I missed that in the contest description... I'll remove the entry until I can fix it. \$\endgroup\$
    – cnamejj
    Jun 21 at 9:24
1
\$\begingroup\$

PowerShell Core, 154 bytes

filter f([char[]]$r){$s="_","-"
($r|%{[string]$c=$_
if(" "-eq$r[$i+1]){$c.ToUpper()}elseif(" "-eq$_){$s[$x+0]
$x=($x+1)%2}else{$c.ToLower()}$i++})-join''}

Try it online!

Ungolfed:

filter f (
    [char[]]$r                     # coerce input string to character array
) {
    $s = "_","-"                   # initialize space array to replace " " with "_" and "-"
    (                              # () needed for -join '' 
        $r | ForEach-Object{
            [string]$c=$_          # [char] lacks .ToUpper(), .ToLower() - coerce back to [string] 
            if(" " -eq $r[$i+1]){  # if next character in array is a space
                $c.ToUpper()       # RETURN uppercase
            }
            elseif(" " -eq $_){    # if space is the current character
                $s[$x+0]           # RETURN indexof space array. incl. "+0" in the index depth so we don't need to initialize $x
                $x=($x+1)%2        # x++ but modulus 2
            }
            else{
                $c.ToLower()       # RETURN lowercase
            }
            $i++                   # increment $i for lookahead
         }
     )-join''                      # [char[]] back to [string]. implicit RETURN from function
 }
\$\endgroup\$
1
1
\$\begingroup\$

Pip, 20 bytes

aR`. `{UC@a."_-"@Uv}

Takes input as a single command-line argument with words space-separated. Attempt This Online!

Explanation

aR`. `{UC@a."_-"@Uv}
a                     Command-line argument
 R                    Replace
  `. `                matches of this regex: any character followed by a space
      {            }  With this callback function:
          a             The matched string
         @              's first character
       UC               Uppercased
           .            Concatenated to
                  v       A number, initially -1
                 U        Increment
                @         and use as a cyclical index into
            "_-"          That string
\$\endgroup\$
1
\$\begingroup\$

Perl 5 + -p055, 26 bytes

s!(.) !uc$1.($|--?$/:_)!eg

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ $|--?$/:_ can be written as < r>^$/ \$\endgroup\$
    – Sisyphus
    Jun 30 at 6:52
0
\$\begingroup\$

sed w/ -E flag, 43 bytes

s/(.) /\U\1_/g
s/([^_]*_){2}/\0-/g
s/_-/-/g

Attempt This Online!

\$\endgroup\$

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.