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