def sum_neighbors(iterable):
"""Summarize adjacent values with the same algebraic sign.
The sum of digits will stay the same.
This can be used to build (not necessarily XHMTL) tables whose cells
should span multiple columns or rows (for smaller size and faster
rendering), e. g. Gantt-like bar charts. For that purpose, positive and
negative values can be used to distinguish cells with a value and empty
cells.
"""
it = iter(iterable)
tmp = it.next()
for x in it:
if (x > 0 and tmp > 0) or (x < 0 and tmp < 0):
tmp += x
else:
yield tmp
tmp = x
yield tmp
def xhtmlize(matrix):
"""Present data in a table with multi-column cells."""
yield '<table>\n'
for row in matrix:
yield ' <tr>\n'
for field in sum_neighbors(row):
span = abs(field)
yield ' <td'
if span > 1:
yield ' colspan="%d"' % span
yield '>%s</td>\n' % ('+' if (field > 0) else '-')
yield ' </tr>\n'
yield '</table>'
expected_example_output = """\
<table>
<tr>
<td colspan="2">-</td>
<td>+</td>
<td>-</td>
<td colspan="3">+</td>
<td>-</td>
<td>+</td>
</tr>
<tr>
<td>+</td>
<td colspan="2">-</td>
<td colspan="3">+</td>
<td colspan="3">-</td>
</tr>
<tr>
<td colspan="9">+</td>
</tr>
<tr>
<td colspan="3">-</td>
<td colspan="2">+</td>
<td colspan="4">-</td>
</tr>
</table>"""
if __name__ == '__main__':
# Example usage:
matrix = (
(-1, -1, 1, -1, 1, 1, 1, -1, 1),
( 1, -1, -1, 1, 1, 1, -1, -1, -1),
( 1, 1, 1, 1, 1, 1, 1, 1, 1),
(-1, -1, -1, 1, 1, -1, -1, -1, -1),
)
output = ''.join(xhtmlize(matrix))
print output
assert output == expected_example_output