Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrated Huffman Coding to Swift 3 syntax #344

Merged
merged 3 commits into from Jan 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions Huffman Coding/Huffman.playground/Contents.swift
Expand Up @@ -3,21 +3,21 @@
import Foundation

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

let huffman1 = Huffman()
let compressedData = huffman1.compressData(originalData)
let compressedData = huffman1.compressData(data: originalData as NSData)
print(compressedData.length)

let frequencyTable = huffman1.frequencyTable()
//print(frequencyTable)

let huffman2 = Huffman()
let decompressedData = huffman2.decompressData(compressedData, frequencyTable: frequencyTable)
let decompressedData = huffman2.decompressData(data: compressedData, frequencyTable: frequencyTable)
print(decompressedData.length)

let s2 = String(data: decompressedData, encoding: NSUTF8StringEncoding)!
let s2 = String(data: decompressedData as Data, encoding: .utf8)!
print(s2)
assert(s1 == s2)
}
34 changes: 17 additions & 17 deletions Huffman Coding/Huffman.playground/Sources/Heap.swift
Expand Up @@ -8,14 +8,14 @@ public struct Heap<T> {
var elements = [T]()

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

/**
* Creates an empty heap.
* The sort function determines whether this is a min-heap or max-heap.
* For integers, > makes a max-heap, < makes a min-heap.
*/
public init(sort: (T, T) -> Bool) {
public init(sort: @escaping (T, T) -> Bool) {
self.isOrderedBefore = sort
}

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

/*
Expand All @@ -45,7 +45,7 @@ public struct Heap<T> {
*/
private mutating func buildHeap(array: [T]) {
elements = array
for i in (elements.count/2 - 1).stride(through: 0, by: -1) {
for i in stride(from: elements.count/2 - 1, to: 0, by: -1) {
shiftDown(index: i, heapSize: elements.count)
}
}
Expand Down Expand Up @@ -96,12 +96,12 @@ public struct Heap<T> {
* Adds a new value to the heap. This reorders the heap so that the max-heap
* or min-heap property still holds. Performance: O(log n).
*/
public mutating func insert(value: T) {
public mutating func insert(_ value: T) {
elements.append(value)
shiftUp(index: elements.count - 1)
}

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

while childIndex > 0 && isOrderedBefore(child, elements[parentIndex]) {
elements[childIndex] = elements[parentIndex]
childIndex = parentIndex
parentIndex = indexOfParent(childIndex)
parentIndex = indexOfParent(i: childIndex)
}

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

while true {
let leftChildIndex = indexOfLeftChild(parentIndex)
let leftChildIndex = indexOfLeftChild(i: parentIndex)
let rightChildIndex = leftChildIndex + 1

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

private func indexOf(element: T, _ i: Int) -> Int? {
private func index(of element: T, _ i: Int) -> Int? {
if i >= count { return nil }
if isOrderedBefore(element, elements[i]) { return nil }
if element == elements[i] { return i }
if let j = indexOf(element, indexOfLeftChild(i)) { return j }
if let j = indexOf(element, indexOfRightChild(i)) { return j }
if let j = index(of: element, indexOfLeftChild(i: i)) { return j }
if let j = index(of: element, indexOfRightChild(i: i)) { return j }
return nil
}
}
30 changes: 15 additions & 15 deletions Huffman Coding/Huffman.playground/Sources/Huffman.swift
Expand Up @@ -29,7 +29,7 @@ public class Huffman {
/* The tree structure. The first 256 entries are for the leaf nodes (not all
of those may be used, depending on the input). We add additional nodes as
we build the tree. */
var tree = [Node](count: 256, repeatedValue: Node())
var tree = [Node](repeating: Node(), count: 256)

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

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

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

let writer = BitWriter()
var ptr = UnsafePointer<UInt8>(data.bytes)
var ptr = data.bytes.assumingMemoryBound(to: UInt8.self)
for _ in 0..<data.length {
let c = ptr.memory
let c = ptr.pointee
let i = Int(c)
traverseTree(writer: writer, nodeIndex: i, childIndex: -1)
ptr = ptr.successor()
Expand All @@ -141,15 +141,15 @@ extension Huffman {
/* Recursively walks the tree from a leaf node up to the root, and then back
again. If a child is the right node, we emit a 0 bit; if it's the left node,
we emit a 1 bit. */
private func traverseTree(writer writer: BitWriter, nodeIndex h: Int, childIndex child: Int) {
private func traverseTree(writer: BitWriter, nodeIndex h: Int, childIndex child: Int) {
if tree[h].parent != -1 {
traverseTree(writer: writer, nodeIndex: tree[h].parent, childIndex: h)
}
if child != -1 {
if child == tree[h].left {
writer.writeBit(true)
writer.writeBit(bit: true)
} else if child == tree[h].right {
writer.writeBit(false)
writer.writeBit(bit: false)
}
}
}
Expand All @@ -158,7 +158,7 @@ extension Huffman {
extension Huffman {
/* Takes a Huffman-compressed NSData object and outputs the uncompressed data. */
public func decompressData(data: NSData, frequencyTable: [Freq]) -> NSData {
restoreTree(frequencyTable)
restoreTree(fromTable: frequencyTable)

let reader = BitReader(data: data)
let outData = NSMutableData()
Expand All @@ -167,7 +167,7 @@ extension Huffman {
var i = 0
while i < byteCount {
var b = findLeafNode(reader: reader, nodeIndex: root)
outData.appendBytes(&b, length: 1)
outData.append(&b, length: 1)
i += 1
}
return outData
Expand All @@ -177,7 +177,7 @@ extension Huffman {
next bit and use that to determine whether to step to the left or right.
When we get to the leaf node, we simply return its index, which is equal to
the original byte value. */
private func findLeafNode(reader reader: BitReader, nodeIndex: Int) -> UInt8 {
private func findLeafNode(reader: BitReader, nodeIndex: Int) -> UInt8 {
var h = nodeIndex
while tree[h].right != -1 {
if reader.readBit() {
Expand Down
8 changes: 4 additions & 4 deletions Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift
Expand Up @@ -8,7 +8,7 @@ public class BitWriter {

public func writeBit(bit: Bool) {
if outCount == 8 {
data.appendBytes(&outByte, length: 1)
data.append(&outByte, length: 1)
outCount = 0
}
outByte = (outByte << 1) | (bit ? 1 : 0)
Expand All @@ -21,7 +21,7 @@ public class BitWriter {
let diff = UInt8(8 - outCount)
outByte <<= diff
}
data.appendBytes(&outByte, length: 1)
data.append(&outByte, length: 1)
}
}
}
Expand All @@ -33,12 +33,12 @@ public class BitReader {
var inCount = 8

public init(data: NSData) {
ptr = UnsafePointer<UInt8>(data.bytes)
ptr = data.bytes.assumingMemoryBound(to: UInt8.self)
}

public func readBit() -> Bool {
if inCount == 8 {
inByte = ptr.memory // load the next byte
inByte = ptr.pointee // load the next byte
inCount = 0
ptr = ptr.successor()
}
Expand Down
8 changes: 4 additions & 4 deletions Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift
Expand Up @@ -11,13 +11,13 @@
queue (largest element first) or a min-priority queue (smallest element first).
*/
public struct PriorityQueue<T> {
private var heap: Heap<T>
fileprivate var heap: Heap<T>

/*
To create a max-priority queue, supply a > sort function. For a min-priority
queue, use <.
*/
public init(sort: (T, T) -> Bool) {
public init(sort: @escaping (T, T) -> Bool) {
heap = Heap(sort: sort)
}

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

public mutating func enqueue(element: T) {
public mutating func enqueue(_ element: T) {
heap.insert(element)
}

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

extension PriorityQueue where T: Equatable {
public func indexOf(element: T) -> Int? {
return heap.indexOf(element)
return heap.index(of: element)
}
}
10 changes: 10 additions & 0 deletions Huffman Coding/Huffman.playground/timeline.xctimeline
Expand Up @@ -2,5 +2,15 @@
<Timeline
version = "3.0">
<TimelineItems>
<LoggerValueHistoryTimelineItem
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"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=350&amp;EndingColumnNumber=21&amp;EndingLineNumber=12&amp;StartingColumnNumber=7&amp;StartingLineNumber=12&amp;Timestamp=505138287.94525"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
</TimelineItems>
</Timeline>