3

I want to be able to rewrite the code in as few lines as possible, possibly in list comprehension syntax. Here is what the output should be:

1|2|3  
4|5|6  
7|8|9

This is what I have thought up. The separator doesn't actually print the "|". Any suggestions?

for i in [1,2,3,4,5,6,7,8,9]:
    print(i, sep = "|", end = "")
    if (i) % 3 == 0:
        print()
midori
  • 4,807
  • 5
  • 34
  • 62
Ricky Su
  • 295
  • 1
  • 7
  • 10

8 Answers8

2

Just print it.

>>> print('1|2|3\n4|5|6\n7|8|9')
1|2|3
4|5|6
7|8|9

To clarify: Yes, I'm obviously assuming that really exactly these numbers shall be printed. I think it's a reasonable assumption, given that the OP also only showed those numbers both in the desired output and in the code, didn't say anything about more flexibility (really should have if it were required), and tic-tac-toe has X and O, not numbers. I suspect this is for showing the user which number to enter for which field during play.

Stefan Pochmann
  • 27,593
  • 8
  • 44
  • 107
2
>>> numbers = range(1, 10)

>>> print(('{}|{}|{}\n' * 3).format(*numbers))
1|2|3
4|5|6
7|8|9
Stefan Pochmann
  • 27,593
  • 8
  • 44
  • 107
  • 1
    small fix to your good solution: print(('{}|{}|{}\n' * 3).format(*range(1,10)).strip('\n')) , it will strip extra new line feed at the end. +1 from my side. – midori Jan 28 '16 at 07:21
  • Yah, I was hoping nobody would notice :-). Or that the OP doesn't care. Alternatively do `print ('{}|{}|{}\n' * 3).format(*range(1, 10)),` in Python 2 or `print(('{}|{}|{}\n' * 3).format(*range(1, 10)), end='')` in Python 3. – Stefan Pochmann Jan 28 '16 at 07:31
1

I like format the most because it offers the best flexibility:

moves = [' ', ' ',' ',' ', 'x',' ',' ', ' ','o']
board = "|{}|{}|{}|\n|{}|{}|{}|\n|{}|{}|{}|\n"
print(board.format(*moves)

Modify the items in that list and run that same print statement for an on-the-go solution.

And there, I managed to slim it down to 3 lines. If I wasn't initializing the list, it would only be 2 lines.

abe
  • 504
  • 4
  • 13
1

the easiest and most elegant way to do it in python 3 using print:

for i in 1,4,7:
    print(i,i+1,i+2, sep='|')

Or using range:

for i in range(1,10,3):
    print(*range(i,i+3), sep='|')

Also there is a good reading here about iterable unpacking operator: Additional Unpacking

Also here is one-liner, not the shortest one but very readable:

print('\n'.join(('{}|{}|{}'.format(i,i+1,i+2) for i in (1,4,7))))

And original one-liner from @Stefan Pochmann's comment:

print(('{}|{}|{}\n' * 3).format(*range(1, 10)), end='')

Output for all is the same:

1|2|3
4|5|6
7|8|9
midori
  • 4,807
  • 5
  • 34
  • 62
0

sep doesn't work when you only give a single thing to print

>>>print(1, sep='|')
1
>>> print(1,2,3, sep='|')
1|2|3

Could do this instead

for i in range(1,10):
    if i % 3 == 0:
        print(i, end="\n")
    else:
        print(i, end="|")

Shortening to a ternary

for i in range(1,10):
    print(i, end="\n") if i % 3 == 0 else print(i, end="|")

Output

1|2|3
4|5|6
7|8|9
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • IMHO this is too much work to print something that will have the same structure each time it is printed. – abe Jan 28 '16 at 03:50
  • @IbrahimAhmed - Two lines is too much work? The rest is just an explanation why it didn't work before – OneCricketeer Jan 28 '16 at 03:51
  • No, the use of a loop that executes 9 times is. 1 simple print statement is all that is necessary once the structure of the item has been chosen. – abe Jan 28 '16 at 03:52
  • This is the only answer that actually answers the question of "why the separator wasn't printing". –  Jan 28 '16 at 04:03
  • @LegoStormtroopr - Right? Thank you. I didn't understand why I got downvoted. – OneCricketeer Jan 28 '16 at 04:05
0

print('\n'.join(['|'.join([str(c) for c in s[i:i+3]]) for i in range(0,9,3)]))

Don't use this (but it works). This assumes your array is in a variable named s

NG.
  • 22,560
  • 5
  • 55
  • 61
  • Why say don't use it? It is fairly natural. – John Coleman Jan 28 '16 at 03:43
  • I just tend to dislike long-ish one liners. I would probably split it into a couple of lines - but trying to meet the fewest lines possible req ;) – NG. Jan 28 '16 at 03:44
  • Is it really necessary to have so much convolution> That's 2 nested loops, and list comprehension. This can be confusing to the python beginners. – abe Jan 28 '16 at 03:51
  • 2
    @IbrahimAhmed OP asked for something as short as possible and explicitly mentioned that list comprehension syntax is okay. – John Coleman Jan 28 '16 at 03:57
  • I've got fewest lines... and fewer characters :P –  Jan 28 '16 at 04:20
0

If you want something that is purely the smallest amount of lines, you can use the ternary syntax:

for i in range(1,10):
    print(i,end='|\n') if (i) % 3 == 0 else print(i,end = "|")

Output:

1|2|3
4|5|6
7|8|9
Brandon Deo
  • 4,195
  • 4
  • 25
  • 42
0

If we're going to code golf, lets code golf properly...

One line:

print("".join(str(i)+'\n|'[i%3>0]for i in range(1,10)))

You can make it one character shorter when you realise that the indexer >0 is actually longer than repeating the pipe (|):

print("".join(str(i)+'\n||'[i%3]for i in range(1,10)))

This gives:

1|2|3
4|5|6
7|8|9

If you need even shorter, a for loop technically doesn't need to be on a new line, also in Python 3 print will print every *args, until the *kwargs.

for i in range(1,10,3):print(i,i+1,i+2,sep='|')
pass # Pass not needed, just shows syntactically how it works.

The first line above is probably the shortest you can get, without just printing the string as is.