Skip to content

Commit 62d1520

Browse files
committed
Change 2D vector to ND vector
1 parent 7981076 commit 62d1520

File tree

2 files changed

+49
-35
lines changed

2 files changed

+49
-35
lines changed

K-Means/K-Means.playground/Contents.swift

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,40 @@
55

66
import Foundation
77

8-
// Need a container to easily hold 2 Dimensional Vector2Ds
9-
class Vector2D: CustomStringConvertible {
10-
var x:Float = 0.0 // x-Coordinate of Vector2D
11-
var y:Float = 0.0 // y-Coordinate of Vector2D
8+
// Need a container to easily hold N Dimensional Vectors
9+
class VectorND: CustomStringConvertible {
10+
private var length:Int = 0
11+
private var data:[Float] = [Float]()
1212

13-
init(x: Float, y: Float) {
14-
self.x = x
15-
self.y = y
13+
init(d:[Float]) {
14+
self.data = d
15+
self.length = d.count
1616
}
1717

18-
var description: String {
19-
return "Vector2D (\(self.x), \(self.y))"
20-
}
18+
var description: String { return "VectorND (\(self.data)" }
19+
func getData() -> [Float] { return data }
20+
func getLength() -> Int { return length }
2121
}
2222

23-
// Ability to use std operators on Vector2D object
24-
func +(left: Vector2D, right: Vector2D) -> Vector2D {
25-
return Vector2D(x: left.x + right.x, y: left.y + right.y)
23+
// Ability to use std operators on VectorND object
24+
func +(left: VectorND, right: VectorND) -> VectorND {
25+
var results = [Float](count: left.getLength(), repeatedValue: 0.0)
26+
for idx in 0..<left.getLength() {
27+
results[idx] = left.getData()[idx] + right.getData()[idx]
28+
}
29+
return VectorND(d: results)
2630
}
27-
func +=(inout left: Vector2D, right: Vector2D) {
31+
func +=(inout left: VectorND, right: VectorND) {
2832
left = left + right
2933
}
30-
func /(left:Vector2D, right: Float) -> Vector2D {
31-
return Vector2D(x: left.x / right, y: left.y / right)
34+
func /(left:VectorND, right: Float) -> VectorND {
35+
var results = [Float](count: left.getLength(), repeatedValue: 0.0)
36+
for (idx, value) in left.getData().enumerate() {
37+
results[idx] = value / right
38+
}
39+
return VectorND(d: results)
3240
}
33-
func /=(inout left: Vector2D, right: Float) {
41+
func /=(inout left: VectorND, right: Float) {
3442
left = left / right
3543
}
3644

@@ -49,16 +57,20 @@ extension Array {
4957
}
5058
}
5159

52-
// Calculates the Euclidean distance between two Vector2Ds
53-
func euclidean(v1:Vector2D, v2:Vector2D) -> Float {
54-
return sqrt(pow((v1.x - v2.x), 2.0) + pow((v1.y - v2.y), 2.0))
60+
// Calculates the Euclidean distance between two VectorNDs
61+
func euclidean(v1:VectorND, v2:VectorND) -> Float {
62+
var result:Float = 0.0
63+
for idx in 0..<v1.getLength() {
64+
result += pow(v1.getData()[idx] - v2.getData()[idx], 2.0)
65+
}
66+
return sqrt(result)
5567
}
5668

5769
// Get the INDEX of nearest Center to X
58-
func nearestCenter(x: Vector2D, Centers: [Vector2D]) -> Int {
70+
func nearestCenter(x: VectorND, Centers: [VectorND]) -> Int {
5971
var nearestDist = FLT_MAX
6072
var minIndex:Int = 0;
61-
// Calculate the distance from Vector2D X to all the centers
73+
// Calculate the distance from VectorND X to all the centers
6274
for (idx, c) in Centers.enumerate() {
6375
let dist = euclidean(x, v2: c)
6476
if dist < nearestDist {
@@ -69,19 +81,20 @@ func nearestCenter(x: Vector2D, Centers: [Vector2D]) -> Int {
6981
return minIndex
7082
}
7183

72-
func kNN(numCenters: Int, convergeDist: Float, points: [Vector2D]) -> [Vector2D] {
84+
func kNN(numCenters: Int, convergeDist: Float, points: [VectorND]) -> [VectorND] {
7385
var centerMoveDist:Float = 0.0
86+
let zeros = [Float](count: points[0].getLength(), repeatedValue: 0.0)
7487

75-
// 1. Choose k Random Vector2Ds as the initial centers
76-
var kCenters:[Vector2D] = points.choose(numCenters)
88+
// 1. Choose k Random VectorNDs as the initial centers
89+
var kCenters:[VectorND] = points.choose(numCenters)
7790

7891
// do following steps until convergence
7992
repeat {
8093
var cnts = [Float](count: numCenters, repeatedValue: 0.0)
81-
var nCenters = [Vector2D](count:numCenters, repeatedValue: Vector2D(x:0, y:0))
82-
// 2. Assign Vector2Ds to centers
83-
// a. Determine which center each Vector2D is closest to
84-
// b. Record how many Vector2Ds are assigned to each center
94+
var nCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros))
95+
// 2. Assign VectorNDs to centers
96+
// a. Determine which center each VectorND is closest to
97+
// b. Record how many VectorNDs are assigned to each center
8598
for p in points {
8699
let c = nearestCenter(p, Centers: kCenters)
87100
cnts[c]++
@@ -102,15 +115,16 @@ func kNN(numCenters: Int, convergeDist: Float, points: [Vector2D]) -> [Vector2D]
102115
} while(centerMoveDist > convergeDist)
103116
return kCenters
104117
}
105-
var points = [Vector2D]()
106-
let lim = 50
118+
119+
var points = [VectorND]()
120+
let lim = 10
107121
for _ in 0..<lim {
108122
let x = Float(arc4random_uniform(UInt32(lim)))
109123
let y = Float(arc4random_uniform(UInt32(lim)))
110-
points.append(Vector2D(x: Float(x), y: y))
124+
points.append(VectorND(d: [x, y]))
111125
}
112126

113127
print("\nCenters")
114-
for c in kNN(10, convergeDist: 0.1, points: points) {
128+
for c in kNN(3, convergeDist: 0.1, points: points) {
115129
print(c)
116-
}
130+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2-
<playground version='5.0' target-platform='osx'>
2+
<playground version='5.0' target-platform='osx' executeOnSourceChanges='false'>
33
<timeline fileName='timeline.xctimeline'/>
44
</playground>

0 commit comments

Comments
 (0)