Skip to content
This repository was archived by the owner on Oct 4, 2020. It is now read-only.

Commit 71cac2b

Browse files
committed
Merge pull request #28 from hdgarrood/intersection-etc
Intersection etc
2 parents ab0fabc + 506b9f9 commit 71cac2b

File tree

4 files changed

+81
-1
lines changed

4 files changed

+81
-1
lines changed

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"package.json"
2323
],
2424
"dependencies": {
25-
"purescript-maps": "^0.5.0"
25+
"purescript-maps": "^0.5.0",
26+
"purescript-tailrec": "^0.3.1"
2627
},
2728
"devDependencies": {
2829
"purescript-assert": "~0.1.1",

docs/Data/Set.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,30 @@ difference :: forall a. (Ord a) => Set a -> Set a -> Set a
139139

140140
Form the set difference
141141

142+
#### `subset`
143+
144+
``` purescript
145+
subset :: forall a. (Ord a) => Set a -> Set a -> Boolean
146+
```
147+
148+
True if and only if every element in the first set
149+
is an element of the second set
150+
151+
#### `properSubset`
152+
153+
``` purescript
154+
properSubset :: forall a. (Ord a) => Set a -> Set a -> Boolean
155+
```
156+
157+
True if and only if the first set is a subset of the second set
158+
and the sets are not equal
159+
160+
#### `intersection`
161+
162+
``` purescript
163+
intersection :: forall a. (Ord a) => Set a -> Set a -> Set a
164+
```
165+
166+
The set of elements which are in both the first and second set
167+
142168

src/Data/Set.purs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ module Data.Set
1919
, union
2020
, unions
2121
, difference
22+
, subset
23+
, properSubset
24+
, intersection
2225
) where
2326

2427
import Prelude
@@ -29,6 +32,18 @@ import Data.Monoid (Monoid)
2932
import Data.Tuple (fst)
3033
import qualified Data.Map as M
3134

35+
import Control.Monad.Eff (runPure, Eff())
36+
import Control.Monad.ST (ST())
37+
import Control.Monad.Rec.Class (tailRecM2)
38+
import Data.Array (nub, length)
39+
import Data.Array.ST
40+
import Data.Array.Unsafe (unsafeIndex)
41+
import qualified Data.List as List
42+
import Data.Either
43+
import Data.Maybe
44+
import Data.Tuple
45+
import Data.Foldable (foldl)
46+
3247
-- | `Set a` represents a set of values of type `a`
3348
data Set a = Set (M.Map a Unit)
3449

@@ -111,3 +126,35 @@ unions = foldl union empty
111126
-- | Form the set difference
112127
difference :: forall a. (Ord a) => Set a -> Set a -> Set a
113128
difference s1 s2 = foldl (flip delete) s1 (toList s2)
129+
130+
-- | True if and only if every element in the first set
131+
-- | is an element of the second set
132+
subset :: forall a. (Ord a) => Set a -> Set a -> Boolean
133+
subset s1 s2 = isEmpty $ s1 `difference` s2
134+
135+
-- | True if and only if the first set is a subset of the second set
136+
-- | and the sets are not equal
137+
properSubset :: forall a. (Ord a) => Set a -> Set a -> Boolean
138+
properSubset s1 s2 = subset s1 s2 && (s1 /= s2)
139+
140+
-- | The set of elements which are in both the first and second set
141+
intersection :: forall a. (Ord a) => Set a -> Set a -> Set a
142+
intersection s1 s2 = fromFoldable $ runPure (runSTArray (emptySTArray >>= intersect)) where
143+
ls = toArray s1
144+
rs = toArray s2
145+
ll = length ls
146+
rl = length rs
147+
intersect :: forall h r. STArray h a -> Eff (st :: ST h | r) (STArray h a)
148+
intersect acc = tailRecM2 go 0 0 where
149+
go l r =
150+
if l < ll && r < rl
151+
then case compare (ls `unsafeIndex` l) (rs `unsafeIndex` r) of
152+
EQ -> do
153+
pushSTArray acc (ls `unsafeIndex` l)
154+
pure $ Left {a: l + 1, b: r + 1}
155+
LT -> pure $ Left {a: l + 1, b: r}
156+
GT -> pure $ Left {a: l, b: r + 1}
157+
else pure $ Right acc
158+
159+
toArray :: forall a. (Ord a) => Set a -> Array a
160+
toArray = List.fromList <<< toList

test/Test/Main.purs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,9 @@ main = do
1818
assert $ S.member 0 set
1919
assert $ S.member 1 set
2020
assert $ S.member 2 set
21+
22+
log "intersection"
23+
do let s1 = S.fromFoldable [1,2,3,4,5]
24+
s2 = S.fromFoldable [2,4,6,8,10]
25+
s3 = S.fromFoldable [2,4]
26+
assert $ S.intersection s1 s2 == s3

0 commit comments

Comments
 (0)