Character Picture Grid
Say you have a list of lists where each value in the inner lists is a one-character string, like this:
grid = [['.', '.', '.', '.', '.', '.'],
['.', 'O', 'O', '.', '.', '.'],
['O', 'O', 'O', 'O', '.', '.'],
['O', 'O', 'O', 'O', 'O', '.'],
['.', 'O', 'O', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', '.'],
['O', 'O', 'O', 'O', '.', '.'],
['.', 'O', 'O', '.', '.', '.'],
['.', '.', '.', '.', '.', '.']]
You can think of grid[x][y]
as being the character at the x- and y-coordinates of a "picture" drawn with text characters. The (0, 0) origin will be in the upper-left corner; the x-coordinates increase going right, and the y-coordinates increase going down.
Copy the previous grid value, and write code that uses it to print the image.
..OO.OO..
.OOOOOOO.
.OOOOOOO.
..OOOOO..
...OOO...
....O....
My solution:
def logic_grid(grid):
for x in range(6):
for y in range(9):
if y < 8:
print(grid[y][x], end='')
else:
print(grid[y][x])
def main():
grid = [['.', '.', '.', '.', '.', '.'],
['.', 'O', 'O', '.', '.', '.'],
['O', 'O', 'O', 'O', '.', '.'],
['O', 'O', 'O', 'O', 'O', '.'],
['.', 'O', 'O', 'O', 'O', 'O'],
['O', 'O', 'O', 'O', 'O', '.'],
['O', 'O', 'O', 'O', '.', '.'],
['.', 'O', 'O', '.', '.', '.'],
['.', '.', '.', '.', '.', '.']]
start = logic_grid(grid)
if __name__ == '__main__':
main()
-
\$\begingroup\$ As it is, your grid represents a list of columns. Would it also be acceptable to rearrange the data to have a list of rows instead, or is this a hard requirement? \$\endgroup\$Schmuddi– Schmuddi2023年06月13日 17:01:37 +00:00Commented Jun 13, 2023 at 17:01
4 Answers 4
In Python, you rarely need to iterate using indexes. Iterate directly over the values themselves, not their indexes. [The latter is what programmers working in poorer languages have to do.]
Question the assignment. In my opinion, the function should not take a grid and print it. Rather, it should return the grid as a string. The latter is more flexible and more in line with the general principle of organizing programs around data-oriented, side-effect-free functions.
Don't hard-code the function to one specific grid. A key purpose of functions is to generalize behavior so it can be reused. If the function hardcodes the grid's dimensions, that generality disappears.
Python iterables can be joined together into strings. This is a basic operation. Take advantage of it.
def main():
# Printing happens out at this level.
grid = [...]
print(grid_to_str(grid))
def grid_to_str(grid):
# No side effects here. Just data in and data out.
# As noted by RootTwo, we have to transpose the grid.
return '\n'.join(
''.join(row)
for row in zip(*grid)
)
if __name__ == '__main__':
main()
-
1\$\begingroup\$ The grid is stored by columns. So the
'\n'.join(''.join(row) ... )
would result in a picture on its side. \$\endgroup\$RootTwo– RootTwo2023年06月13日 07:25:46 +00:00Commented Jun 13, 2023 at 7:25 -
5\$\begingroup\$ @RootTwo Unfortunate. Rotate your monitor? \$\endgroup\$FMc– FMc2023年06月13日 07:42:07 +00:00Commented Jun 13, 2023 at 7:42
-
4\$\begingroup\$ That call to
map
is unnecessary, you can just writefor row in zip(*grid)
. \$\endgroup\$Seb– Seb2023年06月13日 09:35:09 +00:00Commented Jun 13, 2023 at 9:35
Currently you are making assumptions in logic_grid
about grid
. With the current setup it's fine, but if later grid
becomes larger/smaller, the image will not print correctly. Instead of hardcoding in values for the array length, use len
def logic_grid(grid):
# adding validation here to make sure grid is initialized would also be a good idea
for x in range(len(grid[0])):
for y in range(len(grid)):
if y < len(grid)-1:
print(grid[y][x], end='')
else:
print(grid[y][x])
I would also suggest using a better function name as logic_grid
doesn't do anything besides printing, so something like print_grid
or display_grid
would describe what the function does much better.
-
\$\begingroup\$ How do you mean validation? \$\endgroup\$Jarne Vercruysse– Jarne Vercruysse2023年06月12日 12:59:58 +00:00Commented Jun 12, 2023 at 12:59
-
\$\begingroup\$ @JarneVercruysse validation like
type(grid) is list and len(grid)>0)
\$\endgroup\$depperm– depperm2023年06月12日 13:41:27 +00:00Commented Jun 12, 2023 at 13:41
You can use zip
to transpose the itearble of iterables. Like this:
print('\n'.join(''.join(i) for i in zip(*grid)))
(and this code above is the solution)
Another example: dot product of two math vectors with zip
dot_product = lambda x,y:sum(i*j for i,j in zip(x,y))
You don't need zip() and you don't need len(). Just concatenate each row to a string then print the row:
for row in grid:
the_row = ''
for i in row:
the_row += i
print(the_row)
-
\$\begingroup\$ You need zip because the data is sideways. If you try this way the image will be on its side. \$\endgroup\$user3067860– user30678602023年06月13日 18:40:11 +00:00Commented Jun 13, 2023 at 18:40