class TestUnionFind(unittest.TestCase):

    def setUp(self):
        self.N = 10
        self.uf = UF(self.N)
        self.pairs = ((0, 1), (1, 2), (4, 5), (7, 8), (8, 9))

    def test_count(self):
        self.assertEqual(self.uf.count(), self.N)
        self.assertEqual(self.count_sets(), self.N)

        for x, y in self.pairs:
            self.uf.union(x, y)
        n = self.N - len(self.pairs)
        self.assertEqual(self.uf.count(), n)
        self.assertEqual(self.count_sets(), n)

    def test_find(self):
        for i in range(self.N):
            self.assertEqual(self.uf.find(i), i)

        for x, y in self.pairs:
            self.uf.union(x, y)

        for x, y in self.pairs:
            self.assertEqual(self.uf.find(x), self.uf.find(y))

    def test_connected(self):
        for i in range(self.N):
            for j in range(self.N):
                if i == j:
                    continue
                self.assertFalse(self.uf.connected(i, j))

        for x, y in self.pairs:
            self.uf.union(x, y)

        for x, y in self.pairs:
            self.assertTrue(self.uf.connected(x, y))

    def test_str_empty_uf(self):
        self.assertEqual(str(UF(0)), "")

    def test_str_uf(self):
        s = " ".join([str(x) for x in range(self.N)])
        self.assertEqual(str(self.uf), s)

    def count_sets(self):
        return len(set([self.uf.find(x) for x in range(self.N)]))

    def tearDown(self):
        pass
class TestUnionFind(unittest.TestCase):
    def setUp(self):
        self.N = 10
        self.uf = UF(self.N)
        self.pairs = ((0, 1), (1, 2), (4, 5), (7, 8), (8, 9))

    def test_count(self):
        self.assertEqual(self.uf.count(), self.N)
        self.assertEqual(self.count_sets(), self.N)

        for x, y in self.pairs:
            self.uf.union(x, y)
        n = self.N - len(self.pairs)
        self.assertEqual(self.uf.count(), n)
        self.assertEqual(self.count_sets(), n)

    def test_find(self):
        for i in range(self.N):
            self.assertEqual(self.uf.find(i), i)

        for x, y in self.pairs:
            self.uf.union(x, y)

        for x, y in self.pairs:
            self.assertEqual(self.uf.find(x), self.uf.find(y))

    def test_connected(self):
        for i in range(self.N):
            for j in range(self.N):
                if i == j:
                    continue
                self.assertFalse(self.uf.connected(i, j))

        for x, y in self.pairs:
            self.uf.union(x, y)

        for x, y in self.pairs:
            self.assertTrue(self.uf.connected(x, y))

    def test_str_empty_uf(self):
        self.assertEqual(str(UF(0)), "")

    def test_str_uf(self):
        s = " ".join([str(x) for x in range(self.N)])
        self.assertEqual(str(self.uf), s)

    def count_sets(self):
        return len(set([self.uf.find(x) for x in range(self.N)]))

    def tearDown(self):
        pass
示例#3
0
def count_clusters(points, dist):
    n = len(points)
    uf = UnionFind(n)

    # compute all (dx,dy,dz,dt) such that abs(dx) + abs(dy) + abs(dz) + abs(dt) <= 3
    # and don't include (0,0,0,0)
    DIRS = [(dx,dy,dz,dt) for dx in xrange(-dist, dist+1) \
                          for dy in xrange(-dist+abs(dx), dist+1-abs(dx)) \
                          for dz in xrange(-dist+abs(dx)+abs(dy), dist+1-abs(dx)-abs(dy)) \
                          for dt in xrange(-dist+abs(dx)+abs(dy)+abs(dz), dist+1-abs(dx)-abs(dy)-abs(dz)) \
                          if (dx,dy,dz,dt) != (0,0,0,0)]

    # generate a dict of each point to its index
    point_to_index = {p: i for i, p in enumerate(points)}

    # for each connected points, perform a union find between the indices of the two points
    for i in xrange(n):
        x, y, z, t = points[i]
        for dx, dy, dz, dt in DIRS:
            p2 = (x + dx, y + dy, z + dz, t + dt)
            if p2 in point_to_index:
                uf.union(i, point_to_index[p2])

    # return the number of disjoint sets we found
    return uf.count()
示例#4
0
def test_graph_2():
    txs = [[1, 2, 3], [4, 5], [4, 6], [5, 7]]
    uf = UF(8)

    for tx in txs:
        parent = min(tx)
        for node in tx:
            uf.union(parent, node)

    print(uf.connected(5, 6))
    print(uf.find(4))
    print(uf.find(7))
    print(uf.find(3))
    return uf.count()
示例#5
0
def compute_fuzzier(word):
    n = len(word)
    count = 0
    cc = UF(n)
    G = nx.DiGraph()
    G.add_nodes_from(range(n))
    max_positions = {0}
    max_value = word[0]
    unconsidered_positions = [i for i in range(n)]

    i = 0
    j = 2
    unconsidered_positions.remove(0)
    unconsidered_positions.remove(2)

    # Step 1: explore
    while cc.count() > 1:
        mp_list = list(max_positions)
        if cc.count() <= 3 and len(max_positions) > 1 and (mp_list[1] - mp_list[0]) > 1:
            i = mp_list[0] + 1
            j = mp_list[1] + 1

            while True:
                if j == n - 1 or i == mp_list[1]:
                    max_positions = {mp_list[0]}
                    i = mp_list[0]
                    if len(unconsidered_positions) > 0:
                        j = unconsidered_positions[len(unconsidered_positions) // 2]
                        unconsidered_positions.remove(j)
                    elif cc.count() > 1:
                        for new_index in range(n):
                            if cc.find(new_index) != cc.find(i):
                                j = new_index
                                break
                    break
                count += 1
                if i in unconsidered_positions:
                    unconsidered_positions.remove(i)
                if j in unconsidered_positions:
                    unconsidered_positions.remove(j)
                cc.union(i, j)
                if word[i] < word[j]:
                    max_positions = {mp_list[1]}
                    j = mp_list[1]
                    if len(unconsidered_positions) > 0:
                        i = unconsidered_positions[len(unconsidered_positions) // 2]
                        unconsidered_positions.remove(i)
                    elif cc.count() > 1:
                        for new_index in range(n):
                            if cc.find(new_index) != cc.find(j):
                                i = new_index
                                break
                elif word[i] > word[j]:
                    max_positions = {mp_list[0]}
                    i = mp_list[0]
                    if len(unconsidered_positions) > 0:
                        j = unconsidered_positions[len(unconsidered_positions) // 2]
                        unconsidered_positions.remove(j)
                    elif cc.count() > 1:
                        for new_index in range(n):
                            if cc.find(new_index) != cc.find(i):
                                j = new_index
                                break
                else:
                    i += 1
                    j += 1

        else:
            count += 1
            cc.union(i, j)
            if word[i] < word[j]:
                G.add_edge(i, j)
                if word[j] > max_value:
                    max_value = word[j]
                    max_positions = {j}
                if len(unconsidered_positions) > 0:
                    i = unconsidered_positions[len(unconsidered_positions) // 2]
                    unconsidered_positions.remove(i)
                else:
                    for new_index in range(n):
                        if cc.find(new_index) != j:
                            i = new_index
                            break

            elif word[i] > word[j]:
                G.add_edge(j, i)
                if word[i] > max_value:
                    max_value = word[i]
                    max_positions = {i}
                if len(unconsidered_positions) > 0:
                    j = unconsidered_positions[len(unconsidered_positions) // 2]
                    unconsidered_positions.remove(j)
                elif cc.count() > 1:
                    for new_index in range(n):
                        if cc.find(new_index) != cc.find(i):
                            j = new_index
                            break
            else:
                G.add_edge(i, j)
                G.add_edge(j, i)
                if word[i] >= max_value:
                    if i != n-1:
                        max_positions.add(i)
                    if j != n-1:
                        max_positions.add(j)
                if len(unconsidered_positions) > 0:
                    i = unconsidered_positions[0]
                    unconsidered_positions.remove(i)
                elif cc.count() > 1:
                    for new_index in range(n):
                        if cc.find(new_index) != cc.find(j):
                            i = new_index
                            break

    if len(max_positions) == 1:
        return max_positions.pop(), count

    # Step 2 find max suffix from max occurences
    else:
        mp_list = list(set(max_positions))
        mp_list.sort()
        mp_candidates = [mp_list[0]]

        longest_streak = 1
        current_streak = 1
        for i in range(len(mp_list) - 1):
            if mp_list[i + 1] - mp_list[i] == 1:
                # two consecutive maxima
                current_streak += 1
                if current_streak > longest_streak:
                    longest_streak = current_streak
                    mp_candidates = [mp_list[i - current_streak + 2]]
                elif current_streak == longest_streak:
                    mp_candidates.append(mp_list[i - current_streak + 2])
            else:
                current_streak = 1
                if current_streak == longest_streak:
                    mp_candidates.append(mp_list[i + 1])

        if len(mp_candidates) == 1:
            return mp_candidates.pop(), count
        elif mp_candidates[-1] == n - longest_streak:
            mp_candidates.remove(n - longest_streak)
        while len(mp_candidates) > 1:
            count += 1
            i = mp_candidates.pop()
            j = mp_candidates.pop()
            if word[i + 1] > word[j + 1]:
                G.add_edge(j + 1, i + 1)
                mp_candidates.append(i)
            elif word[i + 1] < word[j + 1]:
                G.add_edge(i + 1, j + 1)
                mp_candidates.append(j)
            else:
                return j, count
        return mp_candidates.pop(), count