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?

6 Answers 6

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)
Sign up to request clarification or add additional context in comments.

2 Comments

One minor problem: the OP has trailing borders, so if you're going to use join, you need a + ' |' after the join expression.
I just translated his code example, I assumed he was doing something with _board afterwards anyway.
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):

3 Comments

If you're going for fun with itertools, why not just for row in grouper(5, board): (with the recipe from the docs)?
@abarnert I was looking for something like that but couldn't find it. Thanks :) I'll update my answer with your suggestion soon
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, which I absolutely love.
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

Comments

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.

6 Comments

you dont need to print board though
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?
I'm also learning python as a newbie, thanks for the correction :)
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.
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.
|
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

Comments

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.

1 Comment

If you want to left-align, just use {:<2}.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.