Skip to content

Commit cc42dc1

Browse files
authored
Merge pull request kodecocodes#344 from pbodsk/master
Migrated Huffman Coding to Swift 3 syntax
2 parents 11566eb + 58058cf commit cc42dc1

File tree

9 files changed

+265
-257
lines changed

9 files changed

+265
-257
lines changed

Huffman Coding/Huffman.playground/Contents.swift

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@
33
import Foundation
44

55
let s1 = "so much words wow many compression"
6-
if let originalData = s1.dataUsingEncoding(NSUTF8StringEncoding) {
7-
print(originalData.length)
6+
if let originalData = s1.data(using: .utf8) {
7+
print(originalData.count)
88

99
let huffman1 = Huffman()
10-
let compressedData = huffman1.compressData(originalData)
10+
let compressedData = huffman1.compressData(data: originalData as NSData)
1111
print(compressedData.length)
1212

1313
let frequencyTable = huffman1.frequencyTable()
1414
//print(frequencyTable)
1515

1616
let huffman2 = Huffman()
17-
let decompressedData = huffman2.decompressData(compressedData, frequencyTable: frequencyTable)
17+
let decompressedData = huffman2.decompressData(data: compressedData, frequencyTable: frequencyTable)
1818
print(decompressedData.length)
1919

20-
let s2 = String(data: decompressedData, encoding: NSUTF8StringEncoding)!
20+
let s2 = String(data: decompressedData as Data, encoding: .utf8)!
2121
print(s2)
2222
assert(s1 == s2)
2323
}

Huffman Coding/Huffman.playground/Sources/Heap.swift

+17-17
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ public struct Heap<T> {
88
var elements = [T]()
99

1010
/** Determines whether this is a max-heap (>) or min-heap (<). */
11-
private var isOrderedBefore: (T, T) -> Bool
11+
fileprivate var isOrderedBefore: (T, T) -> Bool
1212

1313
/**
1414
* Creates an empty heap.
1515
* The sort function determines whether this is a min-heap or max-heap.
1616
* For integers, > makes a max-heap, < makes a min-heap.
1717
*/
18-
public init(sort: (T, T) -> Bool) {
18+
public init(sort: @escaping (T, T) -> Bool) {
1919
self.isOrderedBefore = sort
2020
}
2121

@@ -24,9 +24,9 @@ public struct Heap<T> {
2424
* the elements are inserted into the heap in the order determined by the
2525
* sort function.
2626
*/
27-
public init(array: [T], sort: (T, T) -> Bool) {
27+
public init(array: [T], sort: @escaping (T, T) -> Bool) {
2828
self.isOrderedBefore = sort
29-
buildHeap(array)
29+
buildHeap(array: array)
3030
}
3131

3232
/*
@@ -45,7 +45,7 @@ public struct Heap<T> {
4545
*/
4646
private mutating func buildHeap(array: [T]) {
4747
elements = array
48-
for i in (elements.count/2 - 1).stride(through: 0, by: -1) {
48+
for i in stride(from: elements.count/2 - 1, to: 0, by: -1) {
4949
shiftDown(index: i, heapSize: elements.count)
5050
}
5151
}
@@ -96,12 +96,12 @@ public struct Heap<T> {
9696
* Adds a new value to the heap. This reorders the heap so that the max-heap
9797
* or min-heap property still holds. Performance: O(log n).
9898
*/
99-
public mutating func insert(value: T) {
99+
public mutating func insert(_ value: T) {
100100
elements.append(value)
101101
shiftUp(index: elements.count - 1)
102102
}
103103

104-
public mutating func insert<S: SequenceType where S.Generator.Element == T>(sequence: S) {
104+
public mutating func insert<S: Sequence>(sequence: S) where S.Iterator.Element == T {
105105
for value in sequence {
106106
insert(value)
107107
}
@@ -154,15 +154,15 @@ public struct Heap<T> {
154154
* Takes a child node and looks at its parents; if a parent is not larger
155155
* (max-heap) or not smaller (min-heap) than the child, we exchange them.
156156
*/
157-
mutating func shiftUp(index index: Int) {
157+
mutating func shiftUp(index: Int) {
158158
var childIndex = index
159159
let child = elements[childIndex]
160-
var parentIndex = indexOfParent(childIndex)
160+
var parentIndex = indexOfParent(i: childIndex)
161161

162162
while childIndex > 0 && isOrderedBefore(child, elements[parentIndex]) {
163163
elements[childIndex] = elements[parentIndex]
164164
childIndex = parentIndex
165-
parentIndex = indexOfParent(childIndex)
165+
parentIndex = indexOfParent(i: childIndex)
166166
}
167167

168168
elements[childIndex] = child
@@ -176,11 +176,11 @@ public struct Heap<T> {
176176
* Looks at a parent node and makes sure it is still larger (max-heap) or
177177
* smaller (min-heap) than its childeren.
178178
*/
179-
mutating func shiftDown(index index: Int, heapSize: Int) {
179+
mutating func shiftDown(index: Int, heapSize: Int) {
180180
var parentIndex = index
181181

182182
while true {
183-
let leftChildIndex = indexOfLeftChild(parentIndex)
183+
let leftChildIndex = indexOfLeftChild(i: parentIndex)
184184
let rightChildIndex = leftChildIndex + 1
185185

186186
// Figure out which comes first if we order them by the sort function:
@@ -208,16 +208,16 @@ extension Heap where T: Equatable {
208208
/**
209209
* Searches the heap for the given element. Performance: O(n).
210210
*/
211-
public func indexOf(element: T) -> Int? {
212-
return indexOf(element, 0)
211+
public func index(of element: T) -> Int? {
212+
return index(of: element, 0)
213213
}
214214

215-
private func indexOf(element: T, _ i: Int) -> Int? {
215+
private func index(of element: T, _ i: Int) -> Int? {
216216
if i >= count { return nil }
217217
if isOrderedBefore(element, elements[i]) { return nil }
218218
if element == elements[i] { return i }
219-
if let j = indexOf(element, indexOfLeftChild(i)) { return j }
220-
if let j = indexOf(element, indexOfRightChild(i)) { return j }
219+
if let j = index(of: element, indexOfLeftChild(i: i)) { return j }
220+
if let j = index(of: element, indexOfRightChild(i: i)) { return j }
221221
return nil
222222
}
223223
}

Huffman Coding/Huffman.playground/Sources/Huffman.swift

+15-15
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public class Huffman {
2929
/* The tree structure. The first 256 entries are for the leaf nodes (not all
3030
of those may be used, depending on the input). We add additional nodes as
3131
we build the tree. */
32-
var tree = [Node](count: 256, repeatedValue: Node())
32+
var tree = [Node](repeating: Node(), count: 256)
3333

3434
/* This is the last node we add to the tree. */
3535
var root: NodeIndex = -1
@@ -50,10 +50,10 @@ extension Huffman {
5050
occurs. These counts are stored in the first 256 nodes in the tree, i.e.
5151
the leaf nodes. The frequency table used by decompression is derived from
5252
this. */
53-
private func countByteFrequency(data: NSData) {
54-
var ptr = UnsafePointer<UInt8>(data.bytes)
53+
fileprivate func countByteFrequency(inData data: NSData) {
54+
var ptr = data.bytes.assumingMemoryBound(to: UInt8.self)
5555
for _ in 0..<data.length {
56-
let i = Int(ptr.memory)
56+
let i = Int(ptr.pointee)
5757
tree[i].count += 1
5858
tree[i].index = i
5959
ptr = ptr.successor()
@@ -62,7 +62,7 @@ extension Huffman {
6262

6363
/* Takes a frequency table and rebuilds the tree. This is the first step of
6464
decompression. */
65-
private func restoreTree(frequencyTable: [Freq]) {
65+
fileprivate func restoreTree(fromTable frequencyTable: [Freq]) {
6666
for freq in frequencyTable {
6767
let i = Int(freq.byte)
6868
tree[i].count = freq.count
@@ -85,7 +85,7 @@ extension Huffman {
8585

8686
extension Huffman {
8787
/* Builds a Huffman tree from a frequency table. */
88-
private func buildTree() {
88+
fileprivate func buildTree() {
8989
// Create a min-priority queue and enqueue all used nodes.
9090
var queue = PriorityQueue<Node>(sort: { $0.count < $1.count })
9191
for node in tree where node.count > 0 {
@@ -123,13 +123,13 @@ extension Huffman {
123123
extension Huffman {
124124
/* Compresses the contents of an NSData object. */
125125
public func compressData(data: NSData) -> NSData {
126-
countByteFrequency(data)
126+
countByteFrequency(inData: data)
127127
buildTree()
128128

129129
let writer = BitWriter()
130-
var ptr = UnsafePointer<UInt8>(data.bytes)
130+
var ptr = data.bytes.assumingMemoryBound(to: UInt8.self)
131131
for _ in 0..<data.length {
132-
let c = ptr.memory
132+
let c = ptr.pointee
133133
let i = Int(c)
134134
traverseTree(writer: writer, nodeIndex: i, childIndex: -1)
135135
ptr = ptr.successor()
@@ -141,15 +141,15 @@ extension Huffman {
141141
/* Recursively walks the tree from a leaf node up to the root, and then back
142142
again. If a child is the right node, we emit a 0 bit; if it's the left node,
143143
we emit a 1 bit. */
144-
private func traverseTree(writer writer: BitWriter, nodeIndex h: Int, childIndex child: Int) {
144+
private func traverseTree(writer: BitWriter, nodeIndex h: Int, childIndex child: Int) {
145145
if tree[h].parent != -1 {
146146
traverseTree(writer: writer, nodeIndex: tree[h].parent, childIndex: h)
147147
}
148148
if child != -1 {
149149
if child == tree[h].left {
150-
writer.writeBit(true)
150+
writer.writeBit(bit: true)
151151
} else if child == tree[h].right {
152-
writer.writeBit(false)
152+
writer.writeBit(bit: false)
153153
}
154154
}
155155
}
@@ -158,7 +158,7 @@ extension Huffman {
158158
extension Huffman {
159159
/* Takes a Huffman-compressed NSData object and outputs the uncompressed data. */
160160
public func decompressData(data: NSData, frequencyTable: [Freq]) -> NSData {
161-
restoreTree(frequencyTable)
161+
restoreTree(fromTable: frequencyTable)
162162

163163
let reader = BitReader(data: data)
164164
let outData = NSMutableData()
@@ -167,7 +167,7 @@ extension Huffman {
167167
var i = 0
168168
while i < byteCount {
169169
var b = findLeafNode(reader: reader, nodeIndex: root)
170-
outData.appendBytes(&b, length: 1)
170+
outData.append(&b, length: 1)
171171
i += 1
172172
}
173173
return outData
@@ -177,7 +177,7 @@ extension Huffman {
177177
next bit and use that to determine whether to step to the left or right.
178178
When we get to the leaf node, we simply return its index, which is equal to
179179
the original byte value. */
180-
private func findLeafNode(reader reader: BitReader, nodeIndex: Int) -> UInt8 {
180+
private func findLeafNode(reader: BitReader, nodeIndex: Int) -> UInt8 {
181181
var h = nodeIndex
182182
while tree[h].right != -1 {
183183
if reader.readBit() {

Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public class BitWriter {
88

99
public func writeBit(bit: Bool) {
1010
if outCount == 8 {
11-
data.appendBytes(&outByte, length: 1)
11+
data.append(&outByte, length: 1)
1212
outCount = 0
1313
}
1414
outByte = (outByte << 1) | (bit ? 1 : 0)
@@ -21,7 +21,7 @@ public class BitWriter {
2121
let diff = UInt8(8 - outCount)
2222
outByte <<= diff
2323
}
24-
data.appendBytes(&outByte, length: 1)
24+
data.append(&outByte, length: 1)
2525
}
2626
}
2727
}
@@ -33,12 +33,12 @@ public class BitReader {
3333
var inCount = 8
3434

3535
public init(data: NSData) {
36-
ptr = UnsafePointer<UInt8>(data.bytes)
36+
ptr = data.bytes.assumingMemoryBound(to: UInt8.self)
3737
}
3838

3939
public func readBit() -> Bool {
4040
if inCount == 8 {
41-
inByte = ptr.memory // load the next byte
41+
inByte = ptr.pointee // load the next byte
4242
inCount = 0
4343
ptr = ptr.successor()
4444
}

Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
queue (largest element first) or a min-priority queue (smallest element first).
1212
*/
1313
public struct PriorityQueue<T> {
14-
private var heap: Heap<T>
14+
fileprivate var heap: Heap<T>
1515

1616
/*
1717
To create a max-priority queue, supply a > sort function. For a min-priority
1818
queue, use <.
1919
*/
20-
public init(sort: (T, T) -> Bool) {
20+
public init(sort: @escaping (T, T) -> Bool) {
2121
heap = Heap(sort: sort)
2222
}
2323

@@ -33,7 +33,7 @@ public struct PriorityQueue<T> {
3333
return heap.peek()
3434
}
3535

36-
public mutating func enqueue(element: T) {
36+
public mutating func enqueue(_ element: T) {
3737
heap.insert(element)
3838
}
3939

@@ -53,6 +53,6 @@ public struct PriorityQueue<T> {
5353

5454
extension PriorityQueue where T: Equatable {
5555
public func indexOf(element: T) -> Int? {
56-
return heap.indexOf(element)
56+
return heap.index(of: element)
5757
}
5858
}

Huffman Coding/Huffman.playground/timeline.xctimeline

+10
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,15 @@
22
<Timeline
33
version = "3.0">
44
<TimelineItems>
5+
<LoggerValueHistoryTimelineItem
6+
documentLocation = "file:///Users/peter/Programming/iOS/Workspace/swift-algorithm-club/Huffman%20Coding/Huffman.playground#CharacterRangeLen=19&amp;CharacterRangeLoc=678&amp;EndingLineNumber=21&amp;StartingLineNumber=21&amp;Timestamp=505135214.929897"
7+
selectedRepresentationIndex = "0"
8+
shouldTrackSuperviewWidth = "NO">
9+
</LoggerValueHistoryTimelineItem>
10+
<LoggerValueHistoryTimelineItem
11+
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=350&amp;EndingColumnNumber=21&amp;EndingLineNumber=12&amp;StartingColumnNumber=7&amp;StartingLineNumber=12&amp;Timestamp=505138287.94525"
12+
selectedRepresentationIndex = "0"
13+
shouldTrackSuperviewWidth = "NO">
14+
</LoggerValueHistoryTimelineItem>
515
</TimelineItems>
616
</Timeline>

0 commit comments

Comments
 (0)