I’d like to walk you through my thought process solving a problem, or Kata, on Codewars: Transpose two strings in an array

You will be given an array that contains two strings. Your job is to create a function that will take those two strings and transpose them, so that the strings go from top to bottom instead of left to right.

e.g. transposeTwoStrings([‘Hello’,’World’]);

should return

``````H W
e o
l r
l l
o d
``````

A few things to note:

There should be one space in between the two characters You don’t have to modify the case (i.e. no need to change to upper or lower) If one string is longer than the other, there should be a space where the character would be

I typically approach a solution with brute force on my first pass. I decided to loop through “num” times based on the longer string. Then I check for presence for each string’s i’th character, and add the appropriate string to a res array. Increment i by 1 until the loop’s done, and then join the res array’s strings separated by a new line. Like so:

However, looking at other code after I submitted mine, I noticed a refactoring opportunity using the “implicit return-if-true OR” statement, like this: `res << "#{arr[i] || " "} #{arr[i] || " "}"`. So we take all that if/elsif/elsif business and replace it:

I don’t know if it’s called the “implicit return-if-true OR” statement, but it makes sense to me. The next step is to clean up the “num” evaluator. Other solutions used that funny block notation, like so: `num = arr.map(&:length).max`. The long form looks like this:

So it takes each element, or “el”, and transforms the each element into their respective lengths. Calling `.max` at the end returns the maximum value. My current solution works for two strings, but going up to “n” strings in the array, this `#map` method works more appropriately. Another solution is to use “max_by” instead of “map”. I’ll show it here, and in fact I think I like it better. `num = arr.max_by(&:length).length`. The long form is:

It takes the array and returns the element of maximum length, instead of returning an array of lengths to apply a max to. We could have used “size”, but I prefer “length” for strings. Here’s my code so far:

Now, let’s get rid of that “while” loop. We’re effectively iterating from “i = 0” to “i = num”, and plugging in 0 thru “num” for “i” to reference the character in our string. Let’s instead take the range and iterate over each i’th value, and assign strings to our res array that way (and we can remove our `i = 0` variable assignment since it’s given at the range beginning):

I think we can go further still. The `#each` method requires that we assign results to our res array. What if we could instead just transform our range into an array using `#map`? Let’s give it a try.

So we don’t need the res array since each evaluation is the return value given back to our transformed range (to array). But we then need to append `.join("\n")` to the `end`. So far so good. Can we make it better? Cosmetically, yes. We could plug num’s definition into the range, and use `{ }` instead of `do end`. But let’s leave it like so in order that folks following behind us can read it better.