Take an input string \$s\$, and split it into words \$w_1, w_2, ..., w_n\$. If the amount of words is odd, then return \$s\$. Otherwise, for each word: Take the second last letter, and swap it with the first letter keeping capitalization positions. So GolF becomes LogF.

Now check if the amount of words is a multiple of 2, if they are, then take the new words and make another set of words \$q_1, q_2, ..., q_{n/2}\$, where \$q_n\$ is a concatenation of \$w_n\$ and \$w_{2n}\$ before applying the whole thing again to the \$q\$ words.

If the amount of words isn't a multiple of 2, then return \$w\$ separated by spaces.


String: Hello bye hey world woo doo.

  • Split it: [Hello, bye, hey, world, woo, doo]
  • Is the length an even number? Yes, proceed
  • Swap the first and second-last letters: [Lelho, ybe, ehy, lorwd, owo, odo]
  • Is the length an even number? Yes, make new groups of 2: [Lelho ybe, ehy lorwd, owo odo]
  • Swap again: [Belho yle, why lored, dwo ooo]
  • Is the length an even number? No, return Belho yle why lored dwo ooo


  • Input words will always have more than 2 characters
  • Input will always be letters from a-z, capital or lowercase, and separated by a single space
  • Standard loopholes and Default I/O rules apply
  • You may not take input in the form of a word list/array
  • You don't need to handle edge cases

Test Cases

Hello bye hey world woo doo   --> Belho yle why lored dwo ooo
Code golf awesome stuff       --> Goce lodf swesoae ftumf
Very hard code golf challenge --> Very hard code golf challenge (odd length)
Very hard coding stuff        --> Hevy rard sodicg ftunf


This is , so the shortest code (in bytes) wins.

  • 1
    \$\begingroup\$ Shouldn't the last test case return Nevy rard sodicg ftuhf? \$\endgroup\$
    – nwellnhof
    Nov 11, 2018 at 14:56
  • 3
    \$\begingroup\$ Did you mean to type "\$w_{n+1}\$" instead of "\$w_{2n}\$" in "\$q_n\$ is a concatenation of \$w_n\$ and \$w_{2n}\$"? \$\endgroup\$ Nov 11, 2018 at 15:04
  • 1
    \$\begingroup\$ What? Actually, in your example, it looks like \$q_n\$ is \$w_{2n-1}\space w_{2n}\$, not \$w_n\space w_{2n}\$. \$\endgroup\$ Nov 11, 2018 at 15:09
  • 3
    \$\begingroup\$ If we have an even number of words at step #2, we still have an even number of words at step #4, don't we? \$\endgroup\$
    – Arnauld
    Nov 11, 2018 at 15:33
  • 1
    \$\begingroup\$ I think the most confusing part is your example, which contradicts your challenge description. You split the input by spaces, and check if it's even: it is, so proceed. Then you swap for each, and split into groups of two. But then you swap again without checking if the list is odd, which it is. I would expect the output Lelho ybe ehy lorwd owo odo for input Hello bye hey World woo doo. 1. Split by spaces; 2. Check if even: yes, so proceed; 3. Swap for each word; 4. Group per 2 (["Lelho ybe", "ehy lorwd", "owo odo"]); 5. Check if even: no, so output joined by spaces. \$\endgroup\$ Nov 12, 2018 at 8:56

3 Answers 3


Node.js v10.9.0, 171 bytes

s=>(h=a=>a.map(w=>Buffer(w).map((c,i,a)=>(i?i-p?c:x:a[x=c,p=w.length-2])&31|c&96)+''),g=n=>n&1?a.join` `:g(n/2,a=h(h(a).join` `.match(/\S+ \S+/g))))((a=s.split` `).length)

Try it online!


The helper function \$h\$ takes an array of words \$a\$ and apply the letter transformation to each of them.

h = a =>                     // a[] = input array
  a.map(w =>                 // for each word w in a[]:
    Buffer(w)                //   convert w to a Buffer
    .map((c, i, a) =>        //   for each ASCII code c at position i in this array a[]:
      ( i ?                  //     if this is not the first letter:
          i - p ?            //       if this is not the second last letter:
            c                //         just use c
          :                  //       else:
            x                //         use the backup x of the first letter
        :                    //     else:
          a[                 //       use the second last letter
            x = c,           //       save the first letter in x
            p = w.length - 2 //       p = index of the second last letter
          ]                  //
      ) & 31                 //     use the lower bits of the above character
      | c & 96               //     use the upper bits of the current character (case)
    ) + ''                   //   end of inner map(); coerce the Buffer back to a string
  )                          // end of outer map()

Main part:

s => (                       // s = input string
  g = n =>                   // g = recursive function taking the number of words n
    n & 1 ?                  // if n is odd:
      a.join` `              //   stop recursion and return a[] joined with spaces
    :                        // else:
      g(                     //   do a recursive call to g:
        n / 2,               //     with n / 2
        a = h(               //     update a[]:
          h(a)               //       apply the letter transformation
          .join` `           //       join with spaces
          .match(/\S+ \S+/g) //       make groups of 2 words
        )                    //     apply the letter transformation again on the result
      )                      //   end of recursive call
)((a = s.split` `).length)   // initial call to g with a[] = list of words, n = length

Python 3, 189 bytes

J=' '.join
f=lambda w,i:(w[~i].lower(),w[~i].upper())[w[i-1].isupper()]
while~len(s)&1:s=[f(w,1)+w[1:-2]+f(w,-1)+w[-1]for w in s];s=[*map(J,zip(s,s[1:]))][::2]

Try it online!


Charcoal, 68 bytes

≔⪪S θF¬﹪L貫≔¹ηW¬﹪Lθη«≔EE⪪θη⪫λ ⭆⭆Eλ⁻⁻Lλλ⎇∧νξξν⎇№α§λξ↥ν↧νθ≔²η»»⪫θ 

Try it online! Link is to verbose version of code. Explanation:

≔⪪S θ

Split the input on spaces.


Do nothing if the number of words is odd.


Don't pair the words up on the first pass.


Repeat while the number of words is even.

≔EE⪪θη⪫λ ...θ

Pair the words up, map over the paired words, and save the result.


Map each character index to the length of the word minus the index minus 2.


Map each character to itself unless its index or the above calulation is zero in which case use the character at the index given by the above calculation.


Map each character to upper or lower case depending on whether the original character of that word was upper or lower case.


Pair the words up on successive passes.


Join the (remaining) words on spaces and implicitly print.


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