Sorry for the vague title, but I really have no idea what's going on here.
from functools import reduce
arr = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
def strxo(n):
if (n == -1):
return "X"
elif (n == 1):
return "O"
else:
return "_"
def prboard(board):
print(reduce(lambda x, y: x + "\n" + y, list(map(lambda l: reduce(lambda a, b: strxo(a) + strxo(b), l), board))))
prboard(arr)
Desired output:
___
___
___
Real output:
__
__
__
And when I change the final else
on strxo
to return str(n)
instead of return "_"
I get:
000
000
000
Which is what I would expect and the shape I want, but I want to replace those zeroes. What is causing this?
The problem is that your inner most reduce function, the one acting on your sublists, is always turning the second argument to _
:
lambda a, b: strxo(a) + strxo(b)
So, on the last element of that reduce, b
is __
, which gets turned into _
!
You want to map strxo
onto everything first, and then reduce using concatenation.
So you want something like this:
reduce(lambda x, y: x + "\n" + y, map(lambda l: reduce(lambda a, b: a + b, map(strxo, l)), board))
Note, I removed the unecessary call to list
.
But more importantly, stop using reduce
and the concatenation operator to join strings!
It is unnecessarily verbose, and it is inefficient to boot (it will have quadratic time complexity).
Instead, use:
joinstr = ''.join
Which is a perfectly fine function. Functional programming doesn't mean "use map and reduce everywhere possible".
So, here's some good functional programming:
joinstr = ''.join
join_newline = '\n'.join
def board_str(board):
return join_newline(map(lambda l: joinstr(map(strxo,l)), board))
Better yet, you should just use list comprehensions, which are eminently functional constructs (Python stole them from Haskell, btw). It is frequently more readable than map
+ lambda
:
def board_string(board):
return join_newline([joinstr(map(strxo, l)) for l in board])