| 54 | | # THIS IS HARD. D: |
| 55 | | return True |
| | 58 | g = Graph() |
| | 59 | |
| | 60 | def add_edge(b1, b2): |
| | 61 | if b1.ball is not None and b2.ball is not None: |
| | 62 | g.add_edge(b1, b2) |
| | 63 | |
| | 64 | # add all balls and horizontal edges |
| | 65 | for row in self.rows: |
| | 66 | for ball in row.balls: |
| | 67 | if ball.ball is not None: |
| | 68 | g.add_node(ball) |
| | 69 | for b1, b2 in zip(row.balls[:-1], row.balls[1:]): |
| | 70 | add_edge(b1, b2) |
| | 71 | |
| | 72 | # add inter-row connections |
| | 73 | for row, above, below in zip(self.rows[1::2], self.rows[::2], self.rows[2::2] + [BlankRow(0)]): |
| | 74 | for ball, above_left, above_right, below_left, below_right in zip(row.balls, above.balls[:-1], above.balls[1:], below.balls[:-1], below.balls[1:]): |
| | 75 | add_edge(ball, above_left) |
| | 76 | add_edge(ball, above_right) |
| | 77 | add_edge(ball, below_left) |
| | 78 | add_edge(ball, below_right) |
| | 79 | |
| | 80 | top_row = set(self.rows[0].balls) |
| | 81 | valid = True |
| | 82 | for comp in connected_components(g): |
| | 83 | if set(comp).isdisjoint(top_row): |
| | 84 | valid = False |
| | 85 | break |
| | 86 | |
| | 87 | return valid |