Ну zip() тут ни к селу ни к городу... но в принципе можно использовать.
1. Введи строку.
2. Разбей на слова (split() в помощь)
3. Найди такое наибольшее N, что длина списка слов больше N*N. Т.е. если в списке 6 слов, то N будет 2, так как при N = 3 нам понадобится 9 слов для таблицы. Найти можно просто, извлеки корень из длины списка и отбрось дробную часть.
4. Построй список списков. Каждый элемент (т.е. каждый вложенный список) будет одним столбцом таблицы, и будет иметь длину N. Т.е. если оригинальный список слов будет words, то мы получим
columns = [ words[0:N], words[N:2*N], words[2*N:3*N], ... ]
и так далее. Так как число вложенных списков равно N, т.е. заранее неизвестно, это нужно будет сделать циклом.
5. Сделай цикл вида
for row in zip(*columns):
, тогда у тебя zip() возьмёт сначала первый элемент каждого столбца, и скомпонует из них кортеж row. Потом второй из каждого, потом третий, и т.д.
6. Строки из каждого кортеж row нужно вывести, разделив пробелом. Тут можно метод str.join() использовать.