-1

I'm trying to print a table in the second function from the list I created in the first function. My current code doesn't line up properly when printing to the console, and it also prints in order from "left to right" across each row instead of "top to bottom" down each column. I don't know what I need to change in my displayPrimes() function.

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 displayPrimes():
    for row in findPrimes(4027):
        for col in findPrimes(4027):
            product = row * col
            print(product, end = "\t")
            break

# main program
findPrimes(4027)
displayPrimes()
Guohua Cheng
  • 873
  • 6
  • 14
forumer444
  • 35
  • 4
  • Rather than using tabs, this might help: https://stackoverflow.com/questions/5676646/how-can-i-fill-out-a-python-string-with-spaces – Julien Sep 21 '17 at 01:13
  • I appreciate it, but I need to use nested for-loops. The link has stuff that I haven't learned yet and can't use. I'm not asking people to do it for me, just to help me figure it out. – forumer444 Sep 21 '17 at 01:18
  • May I ask what do you want to display on the screen? – Guohua Cheng Sep 21 '17 at 01:45
  • I want to display a table of rows and columns of the list in order. It doesn't have to be a specific number of rows or columns, but I just need the list printed neatly. – forumer444 Sep 21 '17 at 02:13

2 Answers2

2
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 displayPrimes(number, rows=100):
    result_list = [[] for _ in range(rows)]
    primes = findPrimes(number)
    for idx, item in enumerate(primes):
        row_idx = idx % rows
        result_list[row_idx].append("%6d" % item)

    result_str = '\n'.join(['\t'.join(i) for i in result_list])
    return result_str

print(displayPrimes(4027))
Guohua Cheng
  • 873
  • 6
  • 14
1

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.

skrx
  • 18,183
  • 3
  • 28
  • 43