def __init__(self, n): self.n = n self.union_alg = UnionQuickUnionWeighted((n * n) + 2) self.top = (n * n) self.bottom = (n * n) + 1
class Percolation(object): def __init__(self, n): self.n = n self.union_alg = UnionQuickUnionWeighted((n * n) + 2) self.top = (n * n) self.bottom = (n * n) + 1 def _calculate_id(self, row, column): """ Calculates the id which is used in our QuickUnion class. Take for example the following grid of n=5 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 To be able to do unions, we need to know the id of any given x and y. """ return self.n * (row - 1) + column - 1 def open(self, row, column): if row > self.n or column > self.n: raise Exception("out of range") id = self._calculate_id(row, column) if row == 1: self.union_alg.union(self.top, id) if row == self.n: self.union_alg.union(self.bottom, id) # Union with its open neighbours up = (row + 1, column) down = (row - 1, column) left = (row, column - 1) right = (row, column + 1) if up[0] <= self.n and self.is_open(*up): up_id = self._calculate_id(*up) self.union_alg.union(id, up_id) if row > 1 and self.is_open(*down): down_id = self._calculate_id(*down) self.union_alg.union(id, down_id) if right[1] <= self.n and self.is_open(*right): right_id = self._calculate_id(*right) self.union_alg.union(id, right_id) if column > 1 and self.is_open(*left): left_id = self._calculate_id(*left) self.union_alg.union(id, left_id) # In the union class set it as opened self.union_alg.ids[id]['open'] = True def percolates(self): return self.union_alg.connected(self.top, self.bottom) def is_open(self, x, y): id_x_y = self._calculate_id(x, y) return self.union_alg.ids[id_x_y].get('open', False) def is_full(self, x, y): id_x_y = self._calculate_id(x, y) return self.union_alg.connected(id_x_y, self.top)