def calcul_region(self): """etiquète les régions unicolores et calcule leurs tailles L'algo est décrit à https://en.wikipedia.org/wiki/Connected-component_labeling """ union_find = UnionFind() for y in range(Plateau.TAILLEPLATEAU): for x in range(Plateau.TAILLEPLATEAU): self.plateau[x][ y].etiquette_region = Plateau.TAILLEPLATEAU * Plateau.TAILLEPLATEAU # 1re passe etiquette_region = 0 for y in range(Plateau.TAILLEPLATEAU): for x in range(Plateau.TAILLEPLATEAU): c = self.plateau[x][y] t = c.tapis if t != None: etiquettes, mini = self._etiquettes_voisines(x, y, t) if len(etiquettes) == 0: assert (mini == Plateau.TAILLEPLATEAU * Plateau.TAILLEPLATEAU) # pas de voisines étiquetées # on assigne une nouvelle étiquette région c.etiquette_region = etiquette_region # que l'on range dans la structure union_find union_find[etiquette_region] etiquette_region += 1 else: # on affecte la plus petite étiquette voisine c.etiquette_region = mini # les étiquettes voisines sont équivalentes (i.e. même région) union_find.union(etiquettes) ##if debug: ## print(union_find.parents) ## partition={} ## for (k, v) in union_find.parents.items(): ## if v in partition: ## partition[v].append(k) ## else: ## partition[v] = [k] ## print("Partition étiquettes :", partition.values()) # 2e passe et calcul taille région self._taille_region = {} for y in range(Plateau.TAILLEPLATEAU): for x in range(Plateau.TAILLEPLATEAU): c = self.plateau[x][y] nelle_etiquette = union_find[c.etiquette_region] c.etiquette_region = nelle_etiquette if nelle_etiquette not in self._taille_region: self._taille_region[nelle_etiquette] = 1 else: self._taille_region[nelle_etiquette] += 1 # par convention le fond a une région de taille 0 self._taille_region[Plateau.TAILLEPLATEAU * Plateau.TAILLEPLATEAU] = 0 return 0
def cluster2(inputGraph, p, k): print 'start clustering' u = UnionFind.UnionFind() uTmp = UnionFind.UnionFind() for i in p: u.union(i) uTmp.union(i) T = u.parents.values() #print T inputGraph = sorted(inputGraph, key = lambda x: x[2]) print 'parents', u.parents j = 0 for i in inputGraph: j +=1 print j, ":" , u[i[0]], u[i[1]], i[0], i[1] u.union(i[0], i[1]) if j == 8: print u[i[0]], u[i[1]], u.parents break print 'parents', u.parents T = u.parents.values() print "T: ", set(T) if (len(set(T)) == k): print 'stop', k, len(set(T)), T break #print set(u.parents.values()) print 'parents', u.parents G = [] print u.parents for i in inputGraph: print 'test', i, u[i[0]], u[i[1]] if u[i[0]] != u[i[1]]: G.append(i[2]) print G
def test_for_weird_bugs(self): uf = UnionFind(string.ascii_lowercase) uf.union("a", "b") self.assertTrue(uf.find("a", "b")) self.assertTrue(uf.find("b", "a")) self.assertFalse(uf.find("z", "y")) self.assertTrue(uf.find(chr(ord("a")), chr(ord("a") + 1))) self.assertTrue(uf.find(chr(ord("a") + 1), chr(ord("a")))) with self.assertRaises(Exception): uf.find("A", "b")
def kcluster(E, n, nbit): u = UnionFind.UnionFind() pos1 = list(combinations(range(nbit), 1)) print pos1 pos2 = list(combinations(range(nbit), 2)) print pos2 l = len(E) s = set() for i in range(l): s.add(E[i]) n = len(s) for i in range(l): for pos in pos1: c = ord('1') ^ ord(E[i][pos[0]]) etemp = E[i][:pos[0]] + str(c) + E[i][pos[0] + 1:] if etemp in s and u[E[i]] != u[etemp]: u.union(etemp, E[i]) n = n - 1 for pos in pos2: c0 = ord('1') ^ ord(E[i][pos[0]]) c1 = ord('1') ^ ord(E[i][pos[1]]) etemp = E[i][:pos[0]] + str(c0) + E[i][pos[0] + 1:pos[1]] + str( c1) + E[i][pos[1] + 1:] if etemp in s and u[E[i]] != u[etemp]: u.union(etemp, E[i]) n = n - 1 return n
def calcul_region(self): """etiquète les régions unicolores et calcule leurs tailles L'algo est décrit à https://en.wikipedia.org/wiki/Connected-component_labeling """ union_find = UnionFind() for x, colonne in enumerate(self.plateau): for y, case in enumerate(colonne): case.etiquette_region = Plateau.TAILLEPLATEAU * Plateau.TAILLEPLATEAU
def doFindConnectedComponents(self, binary, marked): blobs = [] sets = UnionFind() count = 0 on = 255 for y in xrange(binary.shape[0]): for x in xrange(binary.shape[1]): if binary[y,x] != on: continue # Count the "on" pixels, for debugging count+=1 xyname = sets[y,x] # TODO: there's probably a much better way to do this adjnames = [] if x-1 >= 0 and binary[y,x-1] == on: adjnames.append(sets[y,x-1]) if y-1 >= 0 and binary[y-1,x-1] == on: adjnames.append(sets[y-1,x-1]) # if x+1 < binary.shape[1] and binary[y,x+1] == on: # adjnames.append(sets[y,x+1]) # if y+1 < binary.shape[0] and binary[y+1,x+1] == on: # adjnames.append(sets[y+1,x+1]) if y-1 >= 0 and binary[y-1,x] == on: adjnames.append(sets[y-1,x]) # if x+1 < binary.shape[1] and binary[y-1,x+1] == on: # adjnames.append(sets[y-1,x+1]) # if y+1 < binary.shape[0] and binary[y+1,x] == on: # adjnames.append(sets[y+1,x]) # if x-1 >= 0 and binary[y+1,x-1] == on: # adjnames.append(sets[y+1,x-1]) # For efficiency, no need to union if its the same root while xyname in adjnames: adjnames.remove(xyname) if adjnames: # print "Merging", xyname, "with", adjnames sets.union(xyname, *adjnames) points = self.getPoints(sets) # print count, len(roots), mrw # Mark the largest connected component in the image for p in points: marked[p] = (255, 0, 0)
def test_union_find(self): uf = UnionFind([0, 1, 2, 3, 4, 5]) self.assertFalse(uf.find(0, 1)) self.assertFalse(uf.find(3, 5)) self.assertTrue(uf.find(0, 0)) uf.union(0, 1) uf.union(3, 4) self.assertFalse(uf.find(1, 3)) self.assertTrue(uf.find(0, 1)) self.assertTrue(uf.find(3, 4))
def connectedComponents(G): unionFind = UnionFind() for k in range(G.numNodes): unionFind.makeSet(k) ###creo nuovo insieme con valore k### for i in range(G.numNodes): for j in range(G.numNodes): if G.matrix[i, j] != 0: if unionFind.findSet(i) != unionFind.findSet(j): unionFind.union(i, j) return unionFind
def algKruscal(G): A = [] ###insieme degli archi### unionFind = UnionFind() for i in range(G.numNodes): unionFind.makeSet(i) list = arcOrd( G.matrix) ###in uscita mi serve la lista degli archi ordinati### for i in list: if unionFind.findSet(i.getFirst()) != unionFind.findSet(i.getSecond()): unionFind.union(i.getFirst(), i.getSecond()) A.append(i) return A
def solve(start, end, prime): uf = UnionFind() numbers = range(start, end + 1) for num in numbers: uf.make_set(num) for prime in primes_between(prime, end - start): #print "Merging on", prime divisible = filter(lambda x: not (x % prime), numbers) if divisible: rep = divisible[0] for second in divisible[1:]: #print "Merging %d into %d" % (second, rep) s1, s2 = uf.find(rep), uf.find(second) uf.union(s1, s2) #print uf.as_lists() return len(uf.as_lists())
def MinimumSpanningTree(G): """ Return the minimum spanning tree of an undirected graph G. G should be represented in such a way that G[u][v] gives the length of edge u,v, and G[u][v] should always equal G[v][u]. The tree is returned as a list of edges. """ # Kruskal's algorithm: sort edges by weight, and add them one at a time. # We use Kruskal's algorithm, first because it is very simple to # implement once UnionFind exists, and second, because the only slow # part (the sort) is sped up by being built in to Python. subtrees = UnionFind() tree = [] edges = [(G[u][v],u,v) for u in G for v in G[u]] edges.sort() for W,u,v in edges: if subtrees[u] != subtrees[v]: tree.append((u,v)) subtrees.union(u,v) return tree
def kcluster(E, k, n): u = UnionFind.UnionFind() E = sorted(E, key=edgeweight) l = len(E) for i in range(l): w = E[i] if u[w[0]] != u[w[1]]: if n == k: return w[2] u.union(w[0], w[1]) n = n - 1 else: continue
def doFindConnectedComponents(self, binary, marked): sets = UnionFind() count = 0 on = 255 for y in xrange(binary.shape[0]): for x in xrange(binary.shape[1]): if binary[y, x] != 255: continue # Count the "on" pixels, for debugging count += 1 xyname = sets[y, x] # TODO: there's probably a much better way to do this adjnames = set() #this is hackery and shouldn't work at all if x - 1 >= 0 and binary[y, x - 1] is 255: adjnames.add(sets[y, x - 1]) if y - 1 >= 0 and binary[y - 1, x - 1] is 255: adjnames.add(sets[y - 1, x - 1]) if y - 1 >= 0 and binary[y - 1, x] is 255: adjnames.add(sets[y - 1, x]) # For efficiency, no need to union if its the same root while xyname in adjnames: adjnames.remove(xyname) if adjnames: # print "Merging", xyname, "with", adjnames sets.union(xyname, *adjnames) points = self.getPoints(sets) # print count, len(roots), mrw # Mark the largest connected component in the image for p in points: marked[p] = (255, 0, 0)
def KruskalOnSubset(adjacencyMatrix, nodesSubset): UF = UnionFind(adjacencyMatrix) for i in range(len(nodesSubset)): UF.makeSet(nodesSubset[i]) arcs = setOfArcsOnSubset(adjacencyMatrix,nodesSubset) arcs = sorted(arcs.items(),key = operator.itemgetter(1)) keys = [i[0] for i in arcs] values = [i[1] for i in arcs] spanningTree = dict() for i in range(len(arcs)): if UF.find(keys[i][0]) != UF.find(keys[i][1]): spanningTree[keys[i]] = values[i] UF.union(keys[i][0], keys[i][1]) return spanningTree
def kruskal(eds): uf = UnionFind(6) eds = sorted(eds, key=lambda x: x[-1]) # 按路径长度排序 mst_edges, num = [], 0 for edge in eds: if uf.find(edge[0]) != uf.find(edge[1]): # 如果不构成回路 mst_edges.append(edge) uf.merge(edge[0], edge[1]) num += 1 else: continue if num == 6: break return mst_edges
def Kruskal(adjacencyMatrix): UF = UnionFind(adjacencyMatrix) for i in range(adjacencyMatrix.shape[0]): UF.makeSet(i) arcs = setOfArcs(adjacencyMatrix) #print("arcs1: ",arcs) arcs = sorted(arcs.items(),key = operator.itemgetter(1)) #print("arcs: ", arcs) keys = [i[0] for i in arcs] values = [i[1] for i in arcs] spanningTree = dict() for i in range(len(arcs)): if UF.find(keys[i][0]) != UF.find(keys[i][1]): spanningTree[keys[i]] = values[i] UF.union(keys[i][0], keys[i][1]) return spanningTree
def __init__(self, graph): # Can assume that the graph is connected, since o/w set of trees could become a spanning forest # Make this support spanning forests in a later iteration self.graph = graph E = graph.getEdges() self.graphEdgesSorted = [] for v in E.keys(): for e in E[v]: self.graphEdgesSorted.append(e) self.graphEdgesSorted.sort(key=lambda x: x.w) self.MSTEdges = set() self.nodes = UnionFind.UnionFind() # Kruskal's algorithm to form the set of MST edges for v in self.graph.getVertices(): self.nodes.make_set(v) for e in self.graphEdgesSorted: u, v = e.u, e.v if self.nodes.find_set(u) != self.nodes.find_set(v): self.MSTEdges.add(e) self.nodes.union(u, v)
#line=int(line) #print len(line) if len(line)>3: row=line.split(' ') row[0]=int(row[0]) row[1]=int(row[1]) row[2]=int(row[2]) if m<row[2]: m=row[2] if len(data)<1: data=[(row[0], row[1], row[2])] else: data.append((row[0], row[1], row[2])) inputfile.close() L=sorted(data, key=lambda x: x[2] ) #print L[:10] uf=UnionFind() for i in range(1, 501): uf.makeset(i) #uf.printUF() u=0 while len(uf.clusters)>4: p=L[u][0] q=L[u][1] #print uf.find(p), uf.find(q) uf.union(p,q) #print L[u], p, q, uf.clusters[uf.find(p)[2]] u+=1 #os.system('pause') uf.printUF()
while k * k * k < N: k += 1 sum += 1 j += 1 i += 1 return sum if __name__ == "__main__": # 1 uf = UnionFind.QuickUnionWeighted(10) uf.parse("6-1 1-9 9-0 8-5 7-4 8-4 6-8 7-3 6-2") print str(uf.id).replace(",", "") # UnionFind.parseUnionResult("3 5 5 6 3 3 6 3 3 3") # UnionFind.parseUnionResult("4 7 4 1 4 7 4 4 4 4") # UnionFind.parseUnionResult("9 0 0 0 0 4 1 4 0 5") # UnionFind.parseUnionResult("0 7 8 3 7 6 8 8 3 5") # UnionFind.parseUnionResult("0 7 2 5 4 5 6 7 5 9") # 2 ary = [ int(i) for i in "22 24 28 30 32 49 50 57 64 67 72 77 85 96 98".split() ] binarySearch(ary, 39, 0, 15)
def clusterPred(image, cascade, thresholds, plot = False, maxSpace = 8, minClusterFrac = 10, keypoint = 'left_eye_center'): """ Predicts location of keypoint using center of top-right cluster (that contains at least 1/10 of positives from cascade) Inputs: image: pixel values in numpy array cascade: list of strong classifiers thresholds: list of threshold values distance: max spacing of clustering (default = 5) Output: Graphs predicted location of left-eye keypoint """ # obtain subwindows from image sampleSet = cy.getSubwindows(image) calcIntImage(sampleSet) # convert single strong classifier to a cascade, if necessary if not isinstance(cascade, list): cascade = [cascade] if thresholds is not None: thresholds = [thresholds] # obtain predictions from cascade pred = cascadePred(sampleSet, cascade, thresholds) # obtain index values of locations that have tested positive predIndex = sampleSet[pred == True].index # edgeList consist of tuples of the form (Euclidean distance between point i and point j, i, j) prevIndex = [] edgeList = [] for i in predIndex: prevIndex.append(i) for j in predIndex.diff(prevIndex): if j <= i + len(image) * maxSpace: distance = np.linalg.norm(sampleSet.ix[i,['x','y']] - sampleSet.ix[j,['x','y']]) if distance <= maxSpace: edgeList.append((distance, i, j)) # create union find class that contains all positive locations uf = UF.UnionFind(predIndex) # union points together until edge length exceeds maxSpace for edge in edgeList: uf.union(edge[1],edge[2]) # obtain list of clusters that contain at least 1/minClusterFrac of the positive locations parentTable = Series(uf.parent) parentVals = parentTable.value_counts() parents = parentVals[parentVals > (len(predIndex)/minClusterFrac)].index # obtain the center of each cluster and measure its distance to the top-left corner centers = DataFrame(index = parents, columns = ['x','y']) for parent in parents: centers.ix[parent] = sampleSet.ix[parentTable[parentTable == parent].index, ['x','y']].mean() centers['topLeft'] = (96 - centers['x'])**2 + centers['y']**2 centers = centers.astype(float) # predict location of left eye is the center of teh top-leftmost cluster, plot in red leftEyePred = centers['topLeft'].idxmin() if plot: # plot image and positive locations in blue plt.imshow(image, cmap=cm.Greys_r) for i in sampleSet[pred == True].index: plt.scatter(sampleSet['x'][i], sampleSet['y'][i], color = 'blue') plt.scatter(centers['x'][leftEyePred], centers['y'][leftEyePred], color = 'red') return Series({keypoint + '_x': centers['x'][leftEyePred], keypoint + '_y': centers['y'][leftEyePred]})
def testSize(self): uf = UnionFind(5) self.assertEqual(len(uf), 5) uf.unify(0, 1) uf.find(3) self.assertEquals(len(uf), 5) uf.unify(1, 2) self.assertEquals(len(uf), 5) uf.unify(0, 2) uf.find(1) self.assertEquals(len(uf), 5) uf.unify(2, 1) self.assertEquals(len(uf), 5) uf.unify(3, 4) uf.find(0) self.assertEquals(len(uf), 5) uf.unify(4, 3) uf.find(3) self.assertEquals(len(uf), 5) uf.unify(1, 3) self.assertEquals(len(uf), 5) uf.find(2) uf.unify(4, 0) self.assertEquals(len(uf), 5)
def main(): UnionFind.main(WeightedQuickUnionPathCompression)
def main(): UnionFind.main(WeightedQuickUnion)
for (x, y) in sorted(creationTime.keys()): print("%d\t%d\t%d" % (x, y, creationTime[(x, y)]), file=g) previousCreationTime = creationTime continue # # Calculate ages based on connected components # verticesT0 = [(a, b, False) for (a, b) in pixelsT0] verticesT1 = [(c, d, True) for (c, d) in pixelsT1] # Union-find data structure for the bipartite graph induced by all edges # in the matching. UF = uf.UnionFind(verticesT0 + verticesT1) for edge in edges: (a, b, c, d) = edge u = (a, b, False) v = (c, d, True) # Notice that the order in which the merging is performed does # not matter at all. UF.merge(u, v) components = dict(list()) for root in UF.roots(): components[root] = UF.vertices(root)
""" kruskal.py an implementation of Kruskal's Algorithm for MST by Andrew Jacobson """ import UnionFind # Takes a graph represented by a series of edges # which are represented as a list of tuples # def kruskal(): return None if __name__ == "__main__": #these edges need weights edges = [(1,2),(1,3),(2,3),(3,4),(2,4),(5,4)] a = UnionFind.UF(10) print edges print a
def testComponentSize(self): uf = UnionFind(5) self.assertEqual(uf.componentSize(1), 1) self.assertEqual(uf.componentSize(2), 1) self.assertEqual(uf.componentSize(0), 1) self.assertEqual(uf.componentSize(3), 1) self.assertEqual(uf.componentSize(4), 1) uf.unify(0, 1) self.assertEqual(uf.componentSize(0), 2) self.assertEqual(uf.componentSize(1), 2) self.assertEqual(uf.componentSize(2), 1) self.assertEqual(uf.componentSize(3), 1) self.assertEqual(uf.componentSize(4), 1) uf.unify(1, 0) self.assertEqual(uf.componentSize(0), 2) self.assertEqual(uf.componentSize(1), 2) self.assertEqual(uf.componentSize(2), 1) self.assertEqual(uf.componentSize(3), 1) self.assertEqual(uf.componentSize(4), 1) uf.unify(1, 2) self.assertEqual(uf.componentSize(0), 3) self.assertEqual(uf.componentSize(1), 3) self.assertEqual(uf.componentSize(2), 3) self.assertEqual(uf.componentSize(3), 1) self.assertEqual(uf.componentSize(4), 1) uf.unify(0, 2) self.assertEqual(uf.componentSize(0), 3) self.assertEqual(uf.componentSize(1), 3) self.assertEqual(uf.componentSize(2), 3) self.assertEqual(uf.componentSize(3), 1) self.assertEqual(uf.componentSize(4), 1) uf.unify(2, 1) self.assertEqual(uf.componentSize(0), 3) self.assertEqual(uf.componentSize(1), 3) self.assertEqual(uf.componentSize(2), 3) self.assertEqual(uf.componentSize(3), 1) self.assertEqual(uf.componentSize(4), 1) uf.unify(3, 4) self.assertEqual(uf.componentSize(0), 3) self.assertEqual(uf.componentSize(1), 3) self.assertEqual(uf.componentSize(2), 3) self.assertEqual(uf.componentSize(3), 2) self.assertEqual(uf.componentSize(4), 2) uf.unify(4, 3) self.assertEqual(uf.componentSize(0), 3) self.assertEqual(uf.componentSize(1), 3) self.assertEqual(uf.componentSize(2), 3) self.assertEqual(uf.componentSize(3), 2) self.assertEqual(uf.componentSize(4), 2) uf.unify(1, 3) self.assertEqual(uf.componentSize(0), 5) self.assertEqual(uf.componentSize(1), 5) self.assertEqual(uf.componentSize(2), 5) self.assertEqual(uf.componentSize(3), 5) self.assertEqual(uf.componentSize(4), 5) uf.unify(4, 0) self.assertEqual(uf.componentSize(0), 5) self.assertEqual(uf.componentSize(1), 5) self.assertEqual(uf.componentSize(2), 5) self.assertEqual(uf.componentSize(3), 5) self.assertEqual(uf.componentSize(4), 5)
def testNumComponents(self): uf = UnionFind(5) self.assertEqual(uf.components(), 5) uf.unify(0, 1) self.assertEqual(uf.components(), 4) uf.unify(1, 0) self.assertEqual(uf.components(), 4) uf.unify(1, 2) self.assertEqual(uf.components(), 3) uf.unify(0, 2) self.assertEqual(uf.components(), 3) uf.unify(2, 1) self.assertEqual(uf.components(), 3) uf.unify(3, 4) self.assertEqual(uf.components(), 2) uf.unify(4, 3) self.assertEqual(uf.components(), 2) uf.unify(1, 3) self.assertEqual(uf.components(), 1) uf.unify(4, 0) self.assertEqual(uf.components(), 1)
def main(): UnionFind.main(QuickUnion)
import json import UnionFind from ast import literal_eval # 先建立一个数组存入所有的id arr = [] with open('data.txt', 'r', encoding='UTF-8') as file: line = file.readline() while line: text = json.loads(line) id = text['id'] arr.append(id) line = file.readline() # 根据上面的数组源数据建立并查集 myUnionFind = UnionFind.UnionFind(arr) # 遍历源文件中商品,将商品存入并查集 with open('data.txt', 'r', encoding='UTF-8') as file: line = file.readline() n = 0 while line: text = json.loads(line) id = text['id'] if 'otherFormats' in text.keys(): otherFormats = text['otherFormats'] for format in otherFormats: if format in arr: myUnionFind.union(id, format)
def main(): UnionFind.main(QuickFind)
import tqdm import ujson as json import UnionFind data = [] pid_list = set() with open("data/extract/movie.jl") as movie: for line in movie: j = json.loads(line) data.append(j) pid_list.append(j["pid"]) myUnionFind = UnionFind.UnionFind(pid_list) for line_text in tqdm.tqdm(data): self_pid = line_text["pid"] for asin in line_text["otherFormat"]: if asin in pid_list: myUnionFind.union(self_pid, asin) if "additionalOptions" in line_text: for asin in line_text["additionalOptions"]: if asin in pid_list: myUnionFind.union(self_pid, asin) print("Final Components: ", myUnionFind.n_comps) print("Final Elements: ", myUnionFind.n_elts) with open("components.txt", "w", encoding="utf-8") as outputfile: print(myUnionFind.components(), file=outputfile)
class Go: _BLACK = 1 _WHITE = 2 _EMPTY = 0 uf = UF.UnionFind() def __init__(self, goban_size=9): self._nbWHITE = 0 self._nbBLACK = 0 self._nextPlayer = self._BLACK self._goban_size = goban_size self._state = {'B': 'X', 'W': 'O', '_': '.'} self._goban = np.asarray([[ TK.Token(name='{}{}'.format(i, j), color=self._EMPTY) for j in range(self._goban_size) ] for i in range(self._goban_size)]) self._past_goban = [] self._stack = [] self._successivePass = 0 self._nb_move = 0 self._points = {self._BLACK: 0, self._WHITE: 0} self._MAX_MOVE = goban_size * goban_size * goban_size def reset(self): self.__init__() def _flip(self, player): if player == self._BLACK: return self._WHITE return self._BLACK def get_goban_size(self): return self._goban_size def get_goban(self): return self._goban def is_uf_liberty(self, tk): """ Return the number of degree of liberty """ liberty = 0 tk_root = tk.parent to_study = [tk_root] to_study.extend(tk_root.sons) for _tk in to_study: _tk_pos = [int(_tk.name[0]), int(_tk.name[1])] for _tk_neigh in self.get_neighbors(_tk_pos): if self._goban[_tk_neigh[0], _tk_neigh[1]].color == self._EMPTY: liberty += 1 if liberty == 0: return False, to_study else: return True, to_study def get_legal_moves(self): """ Return an array of legal moves """ legal_moves = [] for l in range(self._goban_size): for c in range(self._goban_size): if self.is_valid_move(self._nextPlayer, [l, c]): legal_moves.append([self._nextPlayer, l, c]) if len(legal_moves) is 0: legal_moves = [[self._nextPlayer, -1, -1]] return legal_moves def get_neighbors(self, pos): """ Return an array of neighbors """ l = pos[0] c = pos[1] neighbors = [] for L in range(-1, 2): for C in range(-1, 2): if L != 0 or C != 0: if np.abs(L) != np.abs(C): if not (l + L == -1 or l + L > self._goban_size - 1 or c + C == -1 or c + C > self._goban_size - 1): neighbors.append(np.array([l + L, c + C])) return neighbors def get_nb_pieces(self): return (self._nbWHITE, self._nbBLACK) def _is_on_board(self, pos): return pos[0] >= 0 and pos[0] < self._goban_size and pos[ 1] >= 0 and pos[1] < self._goban_size #TO DO def _is_never_seen(self, pos, player): game_copy = copy.deepcopy(self) game_copy.push([player, pos[0], pos[1]]) hashed_goban = hash(str(game_copy._goban)) if hashed_goban in self._past_goban: return False else: return True def is_valid_move(self, player, pos): # verify by hash if the board have been already seen # False if there is already a token or out of the board if self._is_on_board(pos) and self._goban[pos[0], pos[1]].color == self._EMPTY: is_never_seen = self._is_never_seen(pos, player) return is_never_seen else: return False #TO DO def capture_token(self, to_capture): for tk in to_capture: tk.__init__(name=tk.name, color=self._EMPTY) self._points[self._nextPlayer] += 1 if self._nextPlayer == self._BLACK: self._nbWHITE -= 1 else: self._nbBLACK -= 1 def place_token(self, pos, player): self._goban[pos[0], pos[1]].color = player tk_pos_neigh = self.get_neighbors(pos) i = 0 while len(tk_pos_neigh) > 0 and i < len(tk_pos_neigh): to_capture = [] tk_pos = tk_pos_neigh[i] tk = self._goban[tk_pos[0], tk_pos[1]] if tk.color == player: self.uf.union(tk, self._goban[pos[0], pos[1]]) # Flatten the tree [[self.uf.find(tk) for tk in l] for l in self._goban] elif tk.color == self._flip(player): is_liberty, to_capture = self.is_uf_liberty(tk) if not is_liberty: self.capture_token(to_capture) else: pass tk_pos_neigh.pop(i) i += 1 hashed_goban = hash(str(self._goban)) self._past_goban.append(hashed_goban) if player == self._BLACK: self._nbBLACK += 1 self._nextPlayer = self._WHITE else: self._nbWHITE += 1 self._nextPlayer = self._BLACK #TO DO def push(self, move): [player, pos] = [move[0], move[1:]] if pos[0] == -1 and pos[1] == -1: # pass self._nextPlayer = self._flip(player) self._stack.append([move, self._successivePass]) self._successivePass += 1 else: self._stack.append([move, self._successivePass]) self._successivePass = 0 self.place_token(pos, player) def is_game_over(self): if self._nb_move < self._MAX_MOVE: # and len(legal_moves)!=0: if self._nbWHITE + self._nbBLACK >= (self._goban_size * self._goban_size): return True else: return False else: return True def count_corner(self): count_b = 0 count_w = 0 for i in range(self._goban_size): for j in range(self._goban_size): if self._goban[i][j].color == self._WHITE: count_w += 1 elif self._goban[i][j].color == self._BLACK: count_b += 1 return count_w, count_b def _piece2str(self, c): if c == self._WHITE: return 'O' elif c == self._BLACK: return 'X' else: return '.' def __str__(self): toreturn = "" for l in self._goban: for c in l: toreturn += self._piece2str(c.color) toreturn += "\n" toreturn += "Next player: " + ("BLACK" if self._nextPlayer == self._BLACK else "WHITE") + "\n" toreturn += str(self._nbBLACK) + " blacks and " + str( self._nbWHITE) + " whites on board\n" toreturn += "(successive pass: "******" )" return toreturn def print_debug(self): print("*" * 20) print(self) print("*" * 20) __repr__ = __str__
def testConnectivity(self): sz = 7 uf = UnionFind(sz) for i in range(sz): self.assertTrue(uf.connected(i, i)) uf.unify(0, 2) self.assertTrue(uf.connected(0, 2)) self.assertTrue(uf.connected(2, 0)) self.assertFalse(uf.connected(0, 1)) self.assertFalse(uf.connected(3, 1)) self.assertFalse(uf.connected(6, 4)) self.assertFalse(uf.connected(5, 0)) for i in range(sz): self.assertTrue(uf.connected(i, i)) uf.unify(3, 1) self.assertTrue(uf.connected(0, 2)) self.assertTrue(uf.connected(2, 0)) self.assertTrue(uf.connected(1, 3)) self.assertTrue(uf.connected(3, 1)) self.assertFalse(uf.connected(0, 1)) self.assertFalse(uf.connected(1, 2)) self.assertFalse(uf.connected(2, 3)) self.assertFalse(uf.connected(1, 0)) self.assertFalse(uf.connected(2, 1)) self.assertFalse(uf.connected(3, 2)) self.assertFalse(uf.connected(1, 4)) self.assertFalse(uf.connected(2, 5)) self.assertFalse(uf.connected(3, 6)) for i in range(sz): self.assertTrue(uf.connected(i, i)) uf.unify(2, 5) self.assertTrue(uf.connected(0, 2)) self.assertTrue(uf.connected(2, 0)) self.assertTrue(uf.connected(1, 3)) self.assertTrue(uf.connected(3, 1)) self.assertTrue(uf.connected(0, 5)) self.assertTrue(uf.connected(5, 0)) self.assertTrue(uf.connected(5, 2)) self.assertTrue(uf.connected(2, 5)) self.assertFalse(uf.connected(0, 1)) self.assertFalse(uf.connected(1, 2)) self.assertFalse(uf.connected(2, 3)) self.assertFalse(uf.connected(1, 0)) self.assertFalse(uf.connected(2, 1)) self.assertFalse(uf.connected(3, 2)) self.assertFalse(uf.connected(4, 6)) self.assertFalse(uf.connected(4, 5)) self.assertFalse(uf.connected(1, 6)) for i in range(sz): self.assertTrue(uf.connected(i, i)) # Connect everything uf.unify(1, 2) uf.unify(3, 4) uf.unify(4, 6) for i in range(sz): for j in range(sz): self.assertTrue(uf.connected(i, j))