I've got a solution that's probably not so easy to understand for a beginner, but it allows you to specify the number of columns.
There's a grouper recipe in the itertools docs which you can use to split an iterable into n-sized groups/tuples. If you figure out how many items there are per column (items_per_column = math.ceil(len(primes)/columns)
) you can pass this number to the grouper
and then use this zip trick to transpose the returned iterable: zip(*iterable)
. Here's a demonstration of this idiom:
>>> lst = [(1,2,3), (4,5,6)]
>>> list(zip(*lst))
[(1, 4), (2, 5), (3, 6)]
The solution:
import math
from itertools import zip_longest
def findPrimes(n):
prime_list = [2]
for number in range(3, n, 2):
if all(number % i != 0 for i in range(2, int(number ** .5) + 1)):
prime_list.append(number)
return prime_list
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
def prime_table(number, columns=8):
"""Rearrange the primes into top to bottom columns."""
primes = findPrimes(number)
# Figure out how many items fit into one column.
items_per_column = math.ceil(len(primes)/columns) # Round up.
# `grouper` splits the list into tuples of length items_per_column.
# Then transpose the groups with `zip(*iterable)`, so that
# the primes are arranged top to bottom.
return zip(*grouper(primes, items_per_column, ''))
def print_table(rows):
for row in rows:
for item in row:
print('{:>6}\t'.format(item), end='')
print()
print_table(prime_table(4027))
Printing more than 10 columns or very large numbers messes up the table.