This repository was archived by the owner on Nov 1, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathIntSet.hs
125 lines (104 loc) · 3 KB
/
IntSet.hs
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
module IntSet (
IntSet,
empty, singleton, union, unionMany, add, addMany,
intersect, delete, deleteMany, minus,
-- map, partition, filter, foldl, foldr,
toList, fromList,
length,
null, isSingleton, intersecting, isSubsetOf, elem
-- replaceMaybe, substitute
) where
import Sort
data IntSet = Nil | Leaf !Int | Fork !IntSet !IntSet
instance Show IntSet where
showsType _ = showString "IntSet"
showsPrec _ Nil = showString "{}"
showsPrec _ s = showString "{" . f (sortLe (<=) (toList s)) . showString "}"
where f [x] = shows x
f (x:xs) = shows x . showString ", " . f xs
instance Eq IntSet where
Nil == Nil = True
Leaf x == Leaf x' = x == x'
Fork l r == Fork l' r' = l == l' && r == r'
_ == _ = False
empty :: IntSet
empty = Nil
singleton :: Int -> IntSet
singleton x = Leaf x
null :: IntSet -> Bool
null Nil = True
null (Leaf _) = False
null (Fork _ _) = False
add :: Int -> IntSet -> IntSet
add x Nil = Leaf x
add x s@(Leaf x') =
if x == x' then
s
else
add x (add x' (Fork Nil Nil))
add x (Fork l r) =
if odd x then
Fork l (add (x `div` 2) r)
else
Fork (add (x `div` 2) l) r
addMany :: [Int] -> IntSet -> IntSet
addMany is s = foldr add s is
elem :: Int -> IntSet -> Bool
elem x Nil = False
elem x (Leaf x') = x == x'
elem x (Fork l r) =
if odd x then
elem (x `div` 2) r
else
elem (x `div` 2) l
union :: IntSet -> IntSet -> IntSet
union Nil t = t
union (Leaf x) t = add x t
union t Nil = t
union t (Leaf x) = add x t
union (Fork l r) (Fork l' r') = Fork (union l l') (union r r')
unionMany :: [IntSet] -> IntSet
unionMany ss = foldr union empty ss
delete :: Int -> IntSet -> IntSet
delete x Nil = Nil
delete x t@(Leaf x') = if x == x' then Nil else t
delete x (Fork l r) =
if odd x then
fork l (delete (x `div` 2) r)
else
fork (delete (x `div` 2) l) r
deleteMany :: [Int] -> IntSet -> IntSet
deleteMany is s = foldr delete s is
fork Nil Nil = Nil
fork Nil (Leaf x) = Leaf (x*2+1)
fork (Leaf x) Nil = Leaf (x*2)
fork l r = Fork l r
intersect :: IntSet -> IntSet -> IntSet
intersect Nil _ = Nil
intersect t@(Leaf x) t' = if elem x t' then t else Nil
intersect _ Nil = Nil
intersect t t'@(Leaf x) = if elem x t then t' else Nil
intersect (Fork l r) (Fork l' r') = fork (intersect l l') (intersect r r')
fromList :: [Int] -> IntSet
fromList xs = foldr add empty xs
toList :: IntSet -> [Int]
toList Nil = []
toList (Leaf x) = [x]
toList (Fork l r) = map (2*) (toList l) ++ map ((1+).(2*)) (toList r)
isSubsetOf :: IntSet -> IntSet -> Bool
isSubsetOf Nil _ = True
isSubsetOf (Leaf x) t = elem x t
isSubsetOf (Fork l r) (Fork l' r') = isSubsetOf l l' && isSubsetOf r r'
isSubsetOf _ _ = False
minus :: IntSet -> IntSet -> IntSet
minus t Nil = t
minus t (Leaf x) = delete x t
minus Nil _ = Nil
minus t@(Leaf x) t' = if elem x t' then Nil else t
minus (Fork l r) (Fork l' r') = fork (minus l l') (minus r r')
length :: IntSet -> Int
length Nil = 0
length (Leaf _) = 1
length (Fork l r) = length l + length r
isSingleton s = length s == 1
intersecting x y = not (null (intersect x y))