Transpose exercise

Hi,
I am having a hard time on this exercise which is supposed to be easy. I spent a few hours on it and still can’t get all the tests passed.

In the instruction, it says padding to the left; does this mean padding before the transpose or after the transposing? It’s not entirely clear which one it meant.

Below is my code and it doesn’t pass the “mixed line length” test case though my output seems to be the same as the expected output visually. Appreciate if someone can take a look at my code and let me know where the problem. I tried with GPT and surprisingly it can’t figure out the issue. It suggested some terrible code to me for the exercise, which is a bit shocking.

def transpose(text: str):
    if not text:
        return ""
    text_rows = text.split('\n')
    max_row_length = max(len(row) for row in text_rows)
    for i in range(len(text_rows)):
        if len(text_rows[i]) < max_row_length:
            text_rows[i] = text_rows[i].ljust(max_row_length)
    res = []
    for i in range(max_row_length):
        new_row = []
        for row in text_rows:
            new_row.append(row[i])
        res.append(''.join(new_row))

    return '\n'.join(res).rstrip()

Hi @stt106 :wave:

The extra space should be added prior to transposing (because then when the rows are transposed, the padding will be to the left).

So I think you might have an issue with the following:

I think your code may be leaving some extra untrimmed space at the ends of lines, which then shows up as extra space at the beginning of the transposed lines, so the output “looks” the same, but is not equal, because there is excess white space.

While str.ljust() can be used without the fill argument, it will pad with space if there isn’t another character given. This can be hard to detect or drop when you are processing and transposing. Recommend you use a fill character like _ or ~ to pad rows. You can then explicitly/easily remove it (because you will know exactly what to replace) as you compose the transposed lines.

There is also no need to do a len() check on each row, since str.ljust() will return the original string if it is already the max length.

Finally, it is clearer and more readable to use enumerate to iterate over a list when you need both the index and the value:

 for index, row in enumerate(text_rows):
        text_rows[index] = row.ljust(max_row_length, '_')

After that, it is a matter of stripping and replacing the padding character in

 res.append(''.join(new_row))

so that the left-padding works in the transposed lines.

str.rstrip() and str.replace() can be really helpful for that. :slightly_smiling_face:

Hope that all makes sense! (let me know if it doesn"t).

One last hint: check out itertools.zip_longest, which can be another way of doing the padding and transpose in fewer steps.

1 Like

Thanks very much for the reply. Your suggests are very helpful.
I am not sure I agree with the expected output in the test for the case of mixed line length.
The test input is “The longest line.\nA long line.\nA longer line.\nA line.”
If I understand the requirement correctly, the last row of the output should be a dot followed by 3 spaces e.g. ". " because the first line of input has the longest length so the last row of output will only have the dot from the first input row and nothing from other input rows.
But in the test, they have an expected output having a last row of a single dot. Here is the expected output from the test case:
"TAAA\nh \nelll\n ooi\nlnnn\nogge\nn e.\nglr\nei \nsnl\ntei\n .n\nl e\ni .\nn\ne\n."
That doesn’t look right to me, or am I missing something here?

I was unable to do this with words easily, so I decided to draw pictures. My apologies. Dong keycaps with markdown wasn’t giving me enough of a contrast to show what is going on, or what “left padding” looks like.

Here is the “The Longest Line” test case, and its transform:

…contrast that with the TEASER test case:

In the first case, the “filler” characters are removed, since they are to the right, and were added to fill out the lines. HOWEVER, in the second test case, the “fillers” were converted to space, because they show up on the left-hand side, and it is the left-hand side that we are padding from.

Both cases needed the fill characters to properly position the letters for transform, but only the second case needed left-padding. Note that spaces in the input need to be preserved, which is why using a placeholder other than whitespace is recommended.

Does that make sense?

5 Likes

wow. I am beyond grateful!
It’s almost unbelievable that you explained it visually.
What can I say, a picture is worth a million words.
Somehow I hope the instruction could be a bit clearer but I totally get it now.
Thanks again for your help. Really appreciated it!

1 Like

We are always trying to improve our exercises, so if you have any thoughts/suggestions on what we do to clarify the instructions for this one (without giving too much away), we’d love to hear them and/or have you submit a PR. :smile:

No pressure or rush – but if you’d like to …

And happy coding on the next challenge!

Thanks again.
Btw, I learnt a ton from all of your submissions too. People like you are who make exercism truly special!

1 Like

I agree, I couldn’t figure out the instructions at all. The section about the “padding” is unclear whether it applies to the input or output. It doesn’t make any sense to transpose a non-rectangular input, and the instructions don’t really clarify the intent of the exercise, so I’m left reading the tests. They don’t call out the need for a placeholder nor describe which placeholders are guaranteed not to appear in the input string (though I guess it’s fine to just pick anything that doesn’t appear in the tests.)

Thank you for the illustration, by the way. That’s incredibly helpful and beautifully done. Please either include that in the instructions, or find a way to describe it in words.