3

I have a list containing the numbers 25-1. I'm trying to print it out like a gameboard, where all the numbers match up:

enter image description here

I found out how to add the lines to the list by doing this:

_b = map(str, board)
_board = ' | '.join(_b)

and I know how to print 5 numbers on each line.. but I'm having trouble getting all the numbers to line up. Is there a way to do this?

Community
  • 1
  • 1
mdegges
  • 963
  • 3
  • 18
  • 39

6 Answers6

4

If you know how long the longest number is going to be, you can use any of these methods:

With the string "5" and a desired width of 3 characters:

  • str.rjust(3) will give the string ' 5'
  • str.ljust(3) will give the string '5 '
  • str.center(3) will give the string ' 5 '.

I tend to like rjust for numbers, as it lines up the places like you learn how to do long addition in elementary school, and that makes me happy ;)

That leaves you with something like:

_b = map(lambda x: str(x).rjust(3), board)
_board = ' | '.join(_b)

or alternately, with generator expressions:

_board = ' | '.join(str(x).rjust(3) for x in board)
Crast
  • 15,996
  • 5
  • 45
  • 53
  • 1
    One minor problem: the OP has trailing borders, so if you're going to use `join`, you need a `+ ' |'` after the `join` expression. – abarnert May 16 '13 at 00:14
  • I just translated his code example, I assumed he was doing something with `_board` afterwards anyway. – Crast May 20 '13 at 22:23
3
board = range(1,26) #the gameboard
for row in [board[i:i+5] for i in range(0,22,5)]: #go over chunks of five
    print('|'.join(["{:<2}".format(n) for n in row])+"|") #justify each number, join by |
    print("-"*15) #print the -'s

Produces

>>> 
1 |2 |3 |4 |5 |
---------------
6 |7 |8 |9 |10|
---------------
11|12|13|14|15|
---------------
16|17|18|19|20|
---------------
21|22|23|24|25|
---------------

Or using the grouper recipe as @abarnert suggested:

for row in grouper(5, board):
jamylak
  • 128,818
  • 30
  • 231
  • 230
HennyH
  • 7,794
  • 2
  • 29
  • 39
  • If you're going for fun with `itertools`, why not just `for row in grouper(5, board):` (with the recipe from the docs)? – abarnert May 16 '13 at 00:11
  • @abarnert I was looking for something like that but couldn't find it. Thanks :) I'll update my answer with your suggestion soon – HennyH May 16 '13 at 00:22
  • 1
    I personally think grouper, and a few of the other recipes, should actually be in itertools. (There's no reason we can't have the source in the recipes section as an example, and _also_ have it in the module, right?) If you agree, you might want to look at [more-itertools](https://pypi.python.org/pypi/more-itertools), which I absolutely love. – abarnert May 16 '13 at 06:09
1
board = range(25, 0, -1)
def printLine():
    print
    print "------------------------"
for c in board:
    print str(c).ljust(2),'|',
    if c % 5 == 1:
        printLine()

That piece of code should work.

albusshin
  • 3,930
  • 3
  • 29
  • 57
  • you dont need to print board though – Serial May 16 '13 at 00:02
  • 1
    Why would you do `str.ljust(str(c), 2)` instead of just `str(c).ljust(2)`? Sure, you _can_ call methods that way in Python, but why? – abarnert May 16 '13 at 00:08
  • I'm also learning python as a newbie, thanks for the correction :) – albusshin May 16 '13 at 00:10
  • 1
    You don't need (or want) semicolons at the end of lines in Python. Also, if you're doing this for fun, check out `board = range(25, 0, -1)`—then you don't need the `sort`. – abarnert May 16 '13 at 00:13
  • Thanks again. I was doing java half an hour ago and the semicolons certainly screwed me up, what is your tip of changing languages with paying attention to the details? – albusshin May 16 '13 at 00:16
  • 1
    I go back and forth between Python, JavaScript, C++, and ObjC. I find that focusing on being idiomatic for each language at the high level usually tricks my brain into getting the details right at the low level. There's no good way to write a series of Python `itertools`-style generator transformations in C++, or an ObjC `doWithBlock:^{…}` internal iteration in Python, or a C++-style `std::transform` into a `back_iterator` in JavaScript, etc., so I don't try. – abarnert May 16 '13 at 00:53
1

Just for fun, here's a 1-liner that creates the numbered rows:

['|'.join([str(y).center(4) for y in x]) for x in map(None,*[reversed(range(1,26))]*5)]

Breaking it up a little, adding rows, still not a clean answer:

nums = map(None,*[reversed(range(1,26))]*5)
rows = ['|'.join([str(y).center(4) for y in x]) for x in nums]
board = ('\n'+'-'*len(rows[0])+'\n').join(rows)
print board
Gary Fixler
  • 5,632
  • 2
  • 23
  • 39
1

A somewhat generalized solution, for a 2D matrix representation:

board = [ [22, 1 , 33], [41, 121, 313], [0, 1, 123112312] ]
maxd = max(len(str(v)) for b in board for v in b) + 1 
l    = []
for b in board:
    l.append("|"+" |".join([ '{n: {w}}'.format(n=v, w=maxd) for v in b]) + " |")
sepl = "\n" + '-'*len(l[0]) + "\n"
print sepl, sepl.join(l), sepl
perreal
  • 94,503
  • 21
  • 155
  • 181
1

I tried a different approach using list comprehensions and the String Format Mini-Language.

boardout = "".join([" {:<2} |".format(x) if (x-1)%5>0 else " {:<2} |\n{}\n".format(x, "-"*25) for x in range(25,0,-1)])
print boardout

This should produce similar output to the OP's expected output. EDIT: Thanks to @abarnert for the shifting tip.

djtubig-malicex
  • 1,018
  • 1
  • 7
  • 11