-2
\$\begingroup\$

Challenge

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.


Example

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

Notes

  • 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

Scoring

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

\$\endgroup\$
  • 1
    \$\begingroup\$ Shouldn't the last test case return Nevy rard sodicg ftuhf? \$\endgroup\$ – nwellnhof Nov 11 '18 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\$ – Erik the Outgolfer Nov 11 '18 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\$ – Erik the Outgolfer Nov 11 '18 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 '18 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\$ – Kevin Cruijssen Nov 12 '18 at 8:56
1
\$\begingroup\$

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!

Commented

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
\$\endgroup\$
0
\$\begingroup\$

Python 3, 189 bytes

J=' '.join
s=input().split()
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]
print(J(s))

Try it online!

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

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.

F¬﹪L貫

Do nothing if the number of words is odd.

≔¹η

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

W¬﹪Lθη«

Repeat while the number of words is even.

≔EE⪪θη⪫λ ...θ

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

Eλ⁻⁻Lλξ²

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.

\$\endgroup\$

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