forked from davemenendez/alive
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsubsets.py
90 lines (68 loc) · 2.17 KB
/
subsets.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
'''
Implements a disjoint subset structure.
'''
class DisjointSubsets(object):
'''
Stores values in one or more subsets. Each value exists in only one
subset at a time. Subsets may be unified.
'''
def __init__(self):
self._parent = {}
# the parent is another element of the subset, or None for the
# representative. Each subset has exactly one representative.
# Must form a path from every element of the subset to the
# representative
self._subset = {}
# the subset, represented as a set
def __contains__(self, key):
return key in self._parent
def key_reps(self):
'Generate pairs consisting of an element and its representative.'
for key in self._parent:
rep = self.rep(key)
yield (key,rep)
def subset_items(self):
'Generate pairs consisting of a representative and its subset.'
return self._subset.iteritems()
def reps(self):
'Generate all representatives.'
return self._subset.iterkeys()
def add_key(self, key):
if key in self._parent:
return
self._parent[key] = None
self._subset[key] = frozenset([key])
def rep(self, key):
if key not in self._parent:
raise KeyError
while self._parent[key] is not None:
key = self._parent[key]
return key
def subset(self, key):
rep = self.rep(key)
return self._subset[rep]
def unify(self, key1, key2):
rep1 = self.rep(key1)
rep2 = self.rep(key2)
if rep1 == rep2:
return
self._parent[rep2] = rep1
subset1 = self._subset[rep1]
subset2 = self._subset.pop(rep2)
self._subset[rep1] = subset1.union(subset2)
def unified(self, key1, key2):
return self.rep(key1) == self.rep(key2)
# ----
class Tag(object):
'''Subclasses of Tag may be used to label objects, so that they
may be added to sets or DisjointSubsets multiple times.'''
def __init__(self, value):
self.val = value
def __eq__(self, other):
return type(self) == type(other) and self.val == other.val
def __ne__(self, other):
return not (self == other)
def __hash__(self):
return hash(type(self)) ^ hash(self.val)
def __repr__(self):
return '{}({!r})'.format(type(self).__name__, self.val)