Skip to content

Commit 5021bc7

Browse files
committed
Added NSCoding conformance.
1 parent e1517dc commit 5021bc7

File tree

4 files changed

+121
-34
lines changed

4 files changed

+121
-34
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>classNames</key>
6+
<dict>
7+
<key>TrieTests</key>
8+
<dict>
9+
<key>testInsertPerformance()</key>
10+
<dict>
11+
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
12+
<dict>
13+
<key>baselineAverage</key>
14+
<real>3.0053</real>
15+
<key>baselineIntegrationDisplayName</key>
16+
<string>Local Baseline</string>
17+
</dict>
18+
</dict>
19+
</dict>
20+
</dict>
21+
</dict>
22+
</plist>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>runDestinationsByUUID</key>
6+
<dict>
7+
<key>6ABF2F62-9363-4450-8DE1-D20F57026950</key>
8+
<dict>
9+
<key>localComputer</key>
10+
<dict>
11+
<key>busSpeedInMHz</key>
12+
<integer>100</integer>
13+
<key>cpuCount</key>
14+
<integer>1</integer>
15+
<key>cpuKind</key>
16+
<string>Intel Core i7</string>
17+
<key>cpuSpeedInMHz</key>
18+
<integer>3300</integer>
19+
<key>logicalCPUCoresPerPackage</key>
20+
<integer>4</integer>
21+
<key>modelCode</key>
22+
<string>MacBookPro13,2</string>
23+
<key>physicalCPUCoresPerPackage</key>
24+
<integer>2</integer>
25+
<key>platformIdentifier</key>
26+
<string>com.apple.platform.macosx</string>
27+
</dict>
28+
<key>targetArchitecture</key>
29+
<string>x86_64</string>
30+
</dict>
31+
</dict>
32+
</dict>
33+
</plist>

Trie/Trie/Trie/Trie.swift

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class TrieNode<T: Hashable> {
4343

4444
/// A trie data structure containing words. Each node is a single
4545
/// character of a word.
46-
class Trie {
46+
class Trie: NSObject, NSCoding {
4747
typealias Node = TrieNode<Character>
4848
/// The number of words in the trie
4949
public var count: Int {
@@ -61,10 +61,31 @@ class Trie {
6161
fileprivate var wordCount: Int
6262

6363
/// Creates an empty trie.
64-
init() {
64+
override init() {
6565
root = Node()
6666
wordCount = 0
6767
}
68+
69+
// MARK: NSCoding
70+
71+
/// Initializes the trie with words from an archive
72+
///
73+
/// - Parameter decoder: Decodes the archive
74+
required convenience init?(coder decoder: NSCoder) {
75+
self.init()
76+
let words = decoder.decodeObject(forKey: "words") as? [String]
77+
for word in words! {
78+
self.insert(word: word)
79+
}
80+
}
81+
82+
/// Encodes the words in the trie by putting them in an array then encoding
83+
/// the array.
84+
///
85+
/// - Parameter coder: The object that will encode the array
86+
func encode(with coder: NSCoder) {
87+
coder.encode(self.words, forKey: "words")
88+
}
6889
}
6990

7091
// MARK: - Adds methods: insert, remove, contains

Trie/Trie/TrieTests/TrieTests.swift

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,20 @@ import XCTest
1212
class TrieTests: XCTestCase {
1313
var wordArray: [String]?
1414
var trie = Trie()
15-
15+
1616
/// Makes sure that the wordArray and trie are initialized before each test.
1717
override func setUp() {
1818
super.setUp()
1919
createWordArray()
2020
insertWordsIntoTrie()
2121
}
22-
23-
/// Don't need to do anything here because the wordArrayu and trie should
22+
23+
/// Don't need to do anything here because the wordArray and trie should
2424
/// stay around.
2525
override func tearDown() {
2626
super.tearDown()
2727
}
28-
28+
2929
/// Reads words from the dictionary file and inserts them into an array. If
3030
/// the word array already has words, do nothing. This allows running all
3131
/// tests without repeatedly filling the array with the same values.
@@ -36,7 +36,7 @@ class TrieTests: XCTestCase {
3636
let resourcePath = Bundle.main.resourcePath! as NSString
3737
let fileName = "dictionary.txt"
3838
let filePath = resourcePath.appendingPathComponent(fileName)
39-
39+
4040
var data: String?
4141
do {
4242
data = try String(contentsOfFile: filePath, encoding: String.Encoding.utf8)
@@ -48,24 +48,23 @@ class TrieTests: XCTestCase {
4848
wordArray = data!.components(separatedBy: "\n")
4949
XCTAssertEqual(wordArray!.count, dictionarySize)
5050
}
51-
51+
5252
/// Inserts words into a trie. If the trie is non-empty, don't do anything.
5353
func insertWordsIntoTrie() {
5454
guard trie.count == 0 else {
5555
return
5656
}
57-
let numberOfWordsToInsert = wordArray!.count
58-
for i in 0..<numberOfWordsToInsert {
59-
trie.insert(word: wordArray![i])
57+
for word in self.wordArray! {
58+
trie.insert(word: word)
6059
}
6160
}
62-
61+
6362
/// Tests that a newly created trie has zero words.
6463
func testCreate() {
6564
let trie = Trie()
6665
XCTAssertEqual(trie.count, 0)
6766
}
68-
67+
6968
/// Tests the insert method
7069
func testInsert() {
7170
let trie = Trie()
@@ -78,7 +77,7 @@ class TrieTests: XCTestCase {
7877
XCTAssertTrue(trie.contains(word: "cut"))
7978
XCTAssertEqual(trie.count, 4)
8079
}
81-
80+
8281
/// Tests the remove method
8382
func testRemove() {
8483
let trie = Trie()
@@ -90,7 +89,7 @@ class TrieTests: XCTestCase {
9089
XCTAssertFalse(trie.contains(word: "cute"))
9190
XCTAssertEqual(trie.count, 1)
9291
}
93-
92+
9493
/// Tests the words property
9594
func testWords() {
9695
let trie = Trie()
@@ -101,52 +100,53 @@ class TrieTests: XCTestCase {
101100
XCTAssertEqual(words[0], "foobar")
102101
XCTAssertEqual(words.count, 1)
103102
}
104-
103+
105104
/// Tests the performance of the insert method.
106105
func testInsertPerformance() {
107-
let trie = Trie()
108106
self.measure() {
109-
let numberOfWordsToInsert = self.wordArray!.count
110-
for i in 0..<numberOfWordsToInsert {
111-
trie.insert(word: self.wordArray![i])
107+
let trie = Trie()
108+
for word in self.wordArray! {
109+
trie.insert(word: word)
112110
}
113111
}
114112
XCTAssertGreaterThan(trie.count, 0)
115113
XCTAssertEqual(trie.count, wordArray?.count)
116114
}
117-
115+
118116
/// Tests the performance of the insert method when the words are already
119117
/// present.
120118
func testInsertAgainPerformance() {
121119
self.measure() {
122-
let numberOfWordsToInsert = self.wordArray!.count
123-
for i in 0..<numberOfWordsToInsert {
124-
self.trie.insert(word: self.wordArray![i])
120+
for word in self.wordArray! {
121+
self.trie.insert(word: word)
125122
}
126123
}
127124
}
128-
125+
129126
/// Tests the performance of the contains method.
130127
func testContainsPerformance() {
131128
self.measure() {
132-
for i in 0..<self.wordArray!.count {
133-
XCTAssertTrue(self.trie.contains(word: self.wordArray![i]))
129+
for word in self.wordArray! {
130+
XCTAssertTrue(self.trie.contains(word: word))
134131
}
135-
136132
}
137133
}
138-
139-
/// Tests the performance of the remove method.
134+
135+
/// Tests the performance of the remove method. Since setup has already put
136+
/// words into the trie, remove them before measuring performance.
140137
func testRemovePerformance() {
138+
for word in self.wordArray! {
139+
self.trie.remove(word: word)
140+
}
141141
self.measure() {
142-
let numberOfWordsToRemove = self.wordArray!.count
143-
for i in 0..<numberOfWordsToRemove {
144-
self.trie.remove(word: self.wordArray![i])
142+
self.insertWordsIntoTrie()
143+
for word in self.wordArray! {
144+
self.trie.remove(word: word)
145145
}
146146
}
147147
XCTAssertEqual(trie.count, 0)
148148
}
149-
149+
150150
/// Tests the performance of the words computed property. Also tests to see
151151
/// if it worked properly.
152152
func testWordsPerformance() {
@@ -159,4 +159,15 @@ class TrieTests: XCTestCase {
159159
XCTAssertTrue(self.trie.contains(word: word))
160160
}
161161
}
162+
163+
/// Tests the archiving and unarchiving of the trie.
164+
func testArchiveAndUnarchive() {
165+
let resourcePath = Bundle.main.resourcePath! as NSString
166+
let fileName = "dictionary-archive"
167+
let filePath = resourcePath.appendingPathComponent(fileName)
168+
NSKeyedArchiver.archiveRootObject(trie, toFile: filePath)
169+
let trieCopy = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as! Trie
170+
XCTAssertEqual(trieCopy.count, trie.count)
171+
172+
}
162173
}

0 commit comments

Comments
 (0)