Skip to content

Commit 40fcc0a

Browse files
committed
UnionFind
1 parent cf571c6 commit 40fcc0a

File tree

5 files changed

+141
-0
lines changed

5 files changed

+141
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//: [Previous](@previous)
2+
3+
import Foundation
4+
5+
var dsu = UnionFind<Int>()
6+
7+
for i in 1...10 {
8+
dsu.addSetWith(i)
9+
}
10+
// now our dsu contains 10 independent sets
11+
// let's divide our numbers into two sets by divisibility by 2
12+
for i in 3...10 {
13+
if i % 2 == 0 {
14+
dsu.unionSetsContaining(2, and: i)
15+
} else {
16+
dsu.unionSetsContaining(1, and: i)
17+
}
18+
}
19+
20+
print(dsu.inSameSet(2, and: 4))
21+
print(dsu.inSameSet(4, and: 6))
22+
print(dsu.inSameSet(6, and: 8))
23+
print(dsu.inSameSet(8, and: 10))
24+
25+
print(dsu.inSameSet(1, and: 3))
26+
print(dsu.inSameSet(3, and: 5))
27+
print(dsu.inSameSet(5, and: 7))
28+
print(dsu.inSameSet(7, and: 9))
29+
30+
print(dsu.inSameSet(7, and: 4))
31+
print(dsu.inSameSet(3, and: 6))
32+
33+
34+
var dsuForStrings = UnionFind<String>()
35+
let words = ["all", "border", "boy", "afternoon", "amazing", "awesome", "best"]
36+
37+
dsuForStrings.addSetWith("a")
38+
dsuForStrings.addSetWith("b")
39+
40+
// In that example we divide strings by its first letter
41+
for word in words {
42+
dsuForStrings.addSetWith(word)
43+
if word.hasPrefix("a") {
44+
dsuForStrings.unionSetsContaining("a", and: word)
45+
} else if word.hasPrefix("b") {
46+
dsuForStrings.unionSetsContaining("b", and: word)
47+
}
48+
}
49+
50+
51+
52+
print(dsuForStrings.inSameSet("a", and: "all"))
53+
print(dsuForStrings.inSameSet("all", and: "awesome"))
54+
print(dsuForStrings.inSameSet("amazing", and: "afternoon"))
55+
56+
print(dsuForStrings.inSameSet("b", and: "boy"))
57+
print(dsuForStrings.inSameSet("best", and: "boy"))
58+
print(dsuForStrings.inSameSet("border", and: "best"))
59+
60+
print(dsuForStrings.inSameSet("amazing", and: "boy"))
61+
print(dsuForStrings.inSameSet("all", and: "border"))
62+
63+
64+
//: [Next](@next)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import Foundation
2+
3+
public struct UnionFind<T: Hashable> {
4+
5+
private var index = [T: Int]()
6+
private var parent = [Int]()
7+
private var size = [Int]()
8+
9+
public init() {}
10+
11+
public mutating func addSetWith(_ element: T) {
12+
index[element] = parent.count
13+
parent.append(parent.count)
14+
size.append(1)
15+
}
16+
17+
public mutating func setOf(_ element: T) -> Int? {
18+
if let indexOfElement = index[element] {
19+
return setByIndex(indexOfElement)
20+
} else {
21+
return nil
22+
}
23+
}
24+
25+
// search up to root
26+
private mutating func setByIndex(_ index: Int) -> Int {
27+
if parent[index] == index { // 1
28+
return index
29+
} else {
30+
parent[index] = setByIndex(parent[index]) // 2
31+
return parent[index] // 3
32+
}
33+
}
34+
35+
// easy
36+
public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool {
37+
if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) {
38+
return firstSet == secondSet
39+
} else {
40+
return false
41+
}
42+
}
43+
44+
public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) {
45+
if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { // 1
46+
if firstSet != secondSet { // 2
47+
if size[firstSet] < size[secondSet] { // 3
48+
parent[firstSet] = secondSet // 4
49+
size[secondSet] += size[firstSet] // 5
50+
} else {
51+
parent[secondSet] = firstSet
52+
size[firstSet] += size[secondSet]
53+
}
54+
}
55+
}
56+
}
57+
58+
}

contents.xcplayground

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
<page name='Stack'/>
66
<page name='Linked List'/>
77
<page name='Trees'/>
8+
<page name='UnionFind'/>
89
</pages>
910
</playground>
Binary file not shown.

xcuserdata/francocedillo.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,22 @@
22
<Bucket
33
type = "1"
44
version = "2.0">
5+
<Breakpoints>
6+
<BreakpointProxy
7+
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
8+
<BreakpointContent
9+
shouldBeEnabled = "Yes"
10+
ignoreCount = "0"
11+
continueAfterRunningActions = "No"
12+
filePath = "Algorithms.playground/Pages/UnionFind.xcplaygroundpage/Sources/UnionFind.swift"
13+
timestampString = "513547899.06388"
14+
startingColumnNumber = "9223372036854775807"
15+
endingColumnNumber = "9223372036854775807"
16+
startingLineNumber = "18"
17+
endingLineNumber = "18"
18+
landmarkName = "setOf(_:)"
19+
landmarkType = "7">
20+
</BreakpointContent>
21+
</BreakpointProxy>
22+
</Breakpoints>
523
</Bucket>

0 commit comments

Comments
 (0)