Swift binary tree list of nodes at given depth - swift

I'm writing a Swift algorithm for a binary tree. My goal is to create a list of nodes at specific depth something like
func listNodeAt(_n: Int) --> [T] {
}
Here is my tree class
public class BinaryTreeNode<T:Comparable> {
//Value and children vars
public var value:T
public var leftChild:BinaryTreeNode?
public var rightChild:BinaryTreeNode?
public weak var parent:BinaryTreeNode?
//Initialization
public convenience init(value: T) {
self.init(value: value, left: nil, right: nil, parent:nil)
}
public init(value:T, left:BinaryTreeNode?, right:BinaryTreeNode?, parent:BinaryTreeNode?) {
self.value = value
self.leftChild = left
self.rightChild = right
self.parent = parent
}
}
I have build a helper function to calculate the depth of a Node
//Depth
public func depth() -> Int {
guard var node = parent else {
return 0
}
var depth = 1
while let parent = node.parent {
depth = depth + 1
node = parent
}
return depth
}
How can we achieve the desired function?

func listNodeAt(_ n: Int) -> [T] {
return getElementsAt(n, node: self)
}
private func getElementsAt(_ n: Int, node: BinaryTreeNode<T>, traversingDepth: Int = 0) -> [T] {
var array = Array<T>()
if traversingDepth < n {
if let left = node.leftChild {
array = array + getElementsAt(n, node: left, traversingDepth: traversingDepth + 1)
}
if let right = node.rightChild {
array = array + getElementsAt(n, node: right, traversingDepth: traversingDepth + 1)
}
} else if traversingDepth == n {
array.append(node.value)
}
return array
}
This is one of the solution. Assuming here the self is the root node.

Related

Updating a binary tree using a pointer

I'm trying to update a self-balancing binary tree. Normally, you can update it by 1) searching a node, 2) deleting it, 3) and inserting the tree with a new node. But, I want to see if this is possible simply by retaining a pointer to a node from the first step and updating it so that I can bypass the deletion and insertion and improve the time complexity, especially when it comes to a large number of nodes.
The tree itself is standard binary search tree.
public class TreeNode<T: Comparable>: Equatable {
public typealias Node = TreeNode<T>
var key: T?
var leftChild: Node?
var rightChild: Node?
fileprivate weak var parent: Node?
var isNullLeaf: Bool {
return key == nil && isLeaf
}
var isLeaf: Bool {
return rightChild == nil && leftChild == nil
}
public init(key: T?, leftChild: Node?, rightChild: Node?, parent: Node?) {
self.key = key
self.leftChild = leftChild
self.rightChild = rightChild
self.parent = parent
self.leftChild?.parent = self
self.rightChild?.parent = self
}
/// Null leaf
public convenience init() {
self.init(key: nil, leftChild: nil, rightChild: nil, parent: nil)
}
static public func == <T>(lhs: TreeNode<T>, rhs: TreeNode<T>) -> Bool {
return lhs.key == rhs.key
}
}
public final class Tree<T: Comparable> {
public typealias Node = TreeNode<T>
fileprivate(set) var root: Node
fileprivate let nullLeaf = Node()
public init() {
root = nullLeaf
}
func search(key: T, f: (inout Node) -> Void) {
search(key: key, node: &root, f: f)
}
fileprivate func search(key: T, node: inout Node, f: (inout Node) -> Void) {
if !node.isNullLeaf {
if let nodeKey = node.key {
/// When a node is found, pass by reference as an argument to a closure so that it retains the connection to the node when it's being update.
if key == nodeKey {
f(&node)
} else if key < nodeKey {
guard node.leftChild != nil else {
return
}
search(key: key, node: &node.leftChild!, f: f)
} else {
guard node.rightChild != nil else {
return
}
search(key: key, node: &node.rightChild!, f: f)
}
}
}
}
public func insert(key: T) {
/// insertion logic
}
/// Other operations
}
My idea was to search the tree through recursion and when a node is found, pass it as an argument to a closure function, which will ultimately be called to update the node. Also, the found node would be pass by reference.
class Test<T: Comparable> {
private(set) var tree = Tree<T>()
func insert(key: T) {
tree.insert(key: key)
}
func update(for node: T, with newNode: T) {
tree.search(key: node) { foundNode in
foundNode.key = newNode
}
}
}
let test = Test<MyNode>()
let node = MyNode()
let anotherNode = MyNode()
test.insert(key: node)
test.update(for: node, with: anotherNode)
The problem is the update doesn't happen. If I search for newly updated node in the tree, it doesn't exist.
Update
Above code is a modified version of a Red-Black tree, specifically modifying the search method to use a pointer instead.
I've tried my idea on a simplified version of a binary search tree below and it seems to be updating the value of a specified node.
public final class BinaryTree<T: Comparable> {
public final class Node<T> {
public var value: T
public var leftChild: Node<T>?
public var rightChild: Node<T>?
public init(value: T, leftChild: Node<T>? = nil, rightChild: Node<T>? = nil) {
self.value = value
self.leftChild = leftChild
self.rightChild = rightChild
}
}
public var rootNode: Node<T>
public init(rootNode: Node<T>) {
self.rootNode = rootNode
}
public func addNodes(to parent: Node<T>, leftChild: Node<T>?, rightChild: Node<T>?) {
parent.leftChild = leftChild
parent.rightChild = rightChild
}
public func searchTree(_ value: T, node: inout Node<T>?, f: (inout Node<T>?) -> Void) {
if node == nil || value == node?.value {
f(&node)
} else if value < node!.value {
searchTree(value, node: &node!.leftChild, f: f)
} else {
searchTree(value, node: &node!.rightChild, f: f)
}
}
}
Tested here.
var rootNode: BinaryTree<Int>.Node<Int>? = BinaryTree<Int>.Node(value: 100, leftChild: nil, rightChild: nil)
let tree = BinaryTree(rootNode: rootNode!)
/// add new nodes. This is not a self-balancing tree so the left child's value has to be smaller than the parent and the right child's value greater than the parent.
let leftChild = BinaryTree<Int>.Node(value: 0, leftChild: nil, rightChild: nil)
let rightChild = BinaryTree<Int>.Node(value: 200, leftChild: nil, rightChild: nil)
tree.addNodes(to: rootNode!, leftChild: leftChild, rightChild: rightChild)
/// the node argument is the starting point of the search so let's start from the root node.
/// the found node will be updated with a new node with a value 50
tree.searchTree(0, node: &rootNode) { foundNode in
let newNode = BinaryTree<Int>.Node(value: 50, leftChild: nil, rightChild: nil)
foundNode = newNode
}
/// The node with a value as 0 is now gone.
tree.searchTree(0, node: &rootNode) { foundNode in
print(foundNode) /// nil
}
/// The node has bee properly updated.
tree.searchTree(50, node: &rootNode) { foundNode in
print(foundNode) /// node with 50 as the value found
}
But can't seem to figure out why the original code isn't updating a node by pointer.
For me the main issue as I mentioned in the comments was with these line of code
fileprivate(set) var root: Node
fileprivate let nullLeaf = Node()
public init() {
root = nullLeaf
}
Root is currently pointing to a nullLeaf which has the following properties:
key = nil
leftChild = nil
self.rightChild = nil
self.parent = nil
I wasn't sure how your insert function was implemented but when I used my insert implementation, this updated the root's properties to the following:
key = nil
leftChild = node
self.rightChild = nil
self.parent = nil
Now when you run your search function which starts at the root:
func search(key: T, f: (inout Node) -> Void) {
search(key: key, node: &root, f: f)
}
fileprivate func search(key: T, node: inout Node, f: (inout Node) -> Void) {
if !node.isNullLeaf {
if let nodeKey = node.key {
/// When a node is found, pass by reference as an
/// argument to a closure so that it retains the
/// connection to the node when it's being update.
if key == nodeKey {
f(&node)
} else if key < nodeKey {
guard node.leftChild != nil else {
return
}
search(key: key, node: &node.leftChild!, f: f)
} else {
guard node.rightChild != nil else {
return
}
search(key: key, node: &node.rightChild!, f: f)
}
}
}
}
if let nodeKey = node.key { is false based on the above root attributes and so it does go into your block where the logic and completion handler gets executed.
Changes and Implementation
Since your main question to answer is
But can't seem to figure out why the original code isn't updating a
node by pointer.
I am using my insertion implementation of a Binary Search Tree even though you mentioned Binary Tree as the main purpose is to show the pointer working.
Here is what I updated to your code:
TreeNode - no changes to your code
// No change to your original code
public class TreeNode<T: Comparable>: Equatable {
public typealias Node = TreeNode<T>
var key: T?
var leftChild: Node?
var rightChild: Node?
fileprivate weak var parent: Node?
var isNullLeaf: Bool {
return key == nil && isLeaf
}
var isLeaf: Bool {
return rightChild == nil && leftChild == nil
}
public init(key: T?, leftChild: Node?, rightChild: Node?, parent: Node?) {
self.key = key
self.leftChild = leftChild
self.rightChild = rightChild
self.parent = parent
self.leftChild?.parent = self
self.rightChild?.parent = self
}
/// Null leaf
public convenience init() {
self.init(key: nil, leftChild: nil, rightChild: nil, parent: nil)
}
static public func == <T>(lhs: TreeNode<T>, rhs: TreeNode<T>) -> Bool {
return lhs.key == rhs.key
}
}
Tree - minor changes and some additions, I have added comments
public final class Tree<T: Comparable> {
public typealias Node = TreeNode<T>
// root starts off as nil
fileprivate(set) var root: Node?
// I don't make use of this
//fileprivate let nullLeaf = Node()
// No initialization of root
public init() {
//root = nullLeaf
}
// No change to your code except to safely evaluate root
func search(key: T, f: (inout Node) -> Void) {
if var root = root {
search(key: key, node: &root, f: f)
}
}
// No change to your code here
fileprivate func search(key: T, node: inout Node, f: (inout Node) -> Void)
{
if !node.isNullLeaf {
if let nodeKey = node.key {
/// When a node is found, pass by reference as an argument
/// to a closure so that it retains the connection to the node
/// when it's being update.
if key == nodeKey {
f(&node)
} else if key < nodeKey {
guard node.leftChild != nil else {
return
}
search(key: key, node: &node.leftChild!, f: f)
} else {
guard node.rightChild != nil else {
return
}
search(key: key, node: &node.rightChild!, f: f)
}
}
}
}
// My insert implementation
public func insert(key: T) {
if let root = insertInternal(key, currentNode: root)
{
self.root = root
}
}
// My insert recursion implementation
private func insertInternal(_ data: T, currentNode: Node?) -> Node?
{
if currentNode == nil
{
let newNode = Node()
newNode.key = data
return newNode
}
if let currentData = currentNode?.key, data > currentData
{
currentNode?.rightChild
= insertInternal(data, currentNode: currentNode?.rightChild)
return currentNode
}
currentNode?.leftChild
= insertInternal(data, currentNode: currentNode?.leftChild)
return currentNode
}
// My implementation ofLevel order / Breadth first traversal
// to display values
func printLevelOrder()
{
print("\n** PRINTING BST IN LEVEL ORDER (BFS) ** ")
var queue: [Node] = []
if let root = root
{
queue.append(root)
}
while !queue.isEmpty
{
let currentNode = queue.removeFirst()
if let currentData = currentNode.key
{
print(currentData)
if let left = currentNode.leftChild
{
queue.append(left)
}
if let right = currentNode.rightChild
{
queue.append(right)
}
}
}
}
}
Test class - no much changes
// No change to your code here except display function
class Test<T: Comparable> {
private(set) var tree = Tree<T>()
func insert(key: T) {
tree.insert(key: key)
}
func update(for node: T, with newNode: T) {
tree.search(key: node) { foundNode in
foundNode.key = newNode
}
}
// Just added a display
func display() {
tree.printLevelOrder()
}
}
Finally here is the main
Test 1 - simple with 1 node
print("Test 1")
var test = Test<Int>()
print("Inserting 10")
test.insert(key: 10)
print("Updating 10 with 8")
test.update(for: 10, with: 8)
test.display()
Output
Test 1
Inserting 10
Updating 10 with 8
** PRINTING BST IN LEVEL ORDER (BFS) **
8
As you can see the exchange of values has happened successfully with the pointer
Test 2 - a little more complex tree with many nodes
print("\n\nTest 2")
test = Test<Int>()
print("Inserting 5")
test.insert(key: 5)
print("Inserting 11")
test.insert(key: 11)
print("Inserting 4")
test.insert(key: 4)
print("Inserting 7")
test.insert(key: 7)
print("Inserting 17")
test.insert(key: 17)
print("Current tree before update")
test.display()
This should give us a binary search tree like this:
And printing the BFS traversal shows us this:
Test 2
Inserting 5
Inserting 11
Inserting 4
Inserting 7
Inserting 17
Current tree before update
** PRINTING BST IN LEVEL ORDER (BFS) **
5
4
11
7
17
Now Let's try to change the value of 7 with 16 which is done with the pointer
print("Updating 7 with 16")
test.update(for: 7, with: 16)
print("Current tree after update")
test.display()
The output is as expected with the value of 7 and swapped with 16
Updating 7 with 16
Current tree after update
** PRINTING BST IN LEVEL ORDER (BFS) **
5
4
11
16
17
Ofcourse, after this swap, the tree is no longer a Binary Search Tree but I think you can see the pointer working well with the above tweaks.

How can I build a recursive function in Swift to return a String?

I have a Node class defined as follows. value: T is a String
class Node<T> {
var value: T
weak var parent: Node?
var children = [Node<T>]()
init(_ value: T) {
self.value = value
}
func add(_ node: Node<T>) {
children.append(node)
node.parent = self
}
}
I'd like to build a function to return a String of the current Node's value and all Parent values. Ideally, the function would be defined in the class. For example,
currentnode.listAllValues()
would return -> "/parent2value/parent1value/currentnodevalue"
So far the following function works with a simple print(), and I've also considered using an inout parameter.
func listAllValues(node: Node<String>) {
print(node.value)
if node.parent?.value != nil {
listAllValues(node: node.parent!)
}
}
You can achieve this with an instance method which calls itself on the parent node first, if there is one:
func listAllValues() -> String {
if let p = parent {
return "\(p.listAllValues())/\(value)"
} else {
return "/\(value)"
}
}
Or as an obfuscated one-liner:
func listAllValues() -> String {
return "\(parent?.listAllValues() ?? "")/\(value)"
}
Example:
let p2 = Node("parent2value")
let p1 = Node("parent1value") ; p2.add(p1)
let n = Node("currentNodeValue") ; p1.add(n)
print(n.listAllValues())
// --> /parent2value/parent1value/currentNodeValue
Here you go:
func desc(_ s:String? = nil) -> String {
var me = String(describing:self.value)
if let prev = s {
me += "/" + prev
}
return self.parent?.desc(me) ?? me
}
Example:
let n = Node("hey")
n.add(Node("ho"))
n.children.first?.add(Node("nonny nonny no"))
let start = n.children.first!.children.first!
print(start.desc())

declare generic class with a generic class as a parameter in swift

I wrote these simple generic classes and it worked great:
class LinkedListNode <T> {
var value: T
var next: LinkedListNode<T>?
weak var prev: LinkedListNode<T>?
init(value: T) {
self.value = value
self.next = nil
}
}
class LinkedList<T> {
var first: LinkedListNode<T>? = nil
var last: LinkedListNode<T>? = nil
var count = 0
#discardableResult func append(_ value: T) -> LinkedListNode<T> {
let new = LinkedListNode(value: value)
new.prev = last
last?.next = new
count += 1
last = new
if first == nil {
first = new
}
return new
}
}
And I used it like:
let list = LinkedList<Int>()
list.append(3)
let lastNode = list.append(5)
Now I realized there are some cases when I need to have a customized node: CustomNode<T>, subclass of LinkedListNode<T>. So I would like to be able to pass the class to be used as the node as:
let list = LinkedList<CustomNode<Int>>()
list.append(3)
let customNode = list.append(5)
How can I declare my class to have it like this or something similar?
I have tried the following declaration but weird errors rise. Is this even possible?
class LinkedList<Node<T>: LinkedListNode<T>> { ...
Update 2019/07/26.
Even with Kamran's approach this method does not compile. I am not sure if this is doable without a protocol. See my comment on Kamran's answer.
func remove(node: LinkedListNode<T>) { // change to `func remove(node: U)`
node.next?.prev = node.prev
node.prev?.next = node.next
if node === first {
first = first?.next
}
if node === last {
last = last?.prev // Error here: "Cannot assign value of LinkedListNode<T>? to U?"
}
}
The syntax you are trying can be achieved as below,
class LinkedListNode <T> {
var value: T
var next: LinkedListNode<T>?
weak var prev: LinkedListNode<T>?
required init(value: T) {
self.value = value
self.next = nil
}
}
class GenericCustomNode<T>: LinkedListNode<T> {
required init(value: T) {
super.init(value: value)
}
}
class NonGenericCustomNode: LinkedListNode<Int> {
required init(value: Int) {
super.init(value: value)
}
}
class LinkedList<T, U: LinkedListNode<T>> {
var first: U? = nil
var last: U? = nil
var count = 0
#discardableResult func append(_ value: T) -> U {
let new = U(value: value)
new.prev = last
last?.next = new
count += 1
last = new
if first == nil {
first = new
}
return new
}
func remove(node: U) {
node.next?.prev = node.prev
node.prev?.next = node.next
if node === first {
first = first?.next as? U
}
if node === last {
last = last?.prev as? U
}
}
}
Usage:
let list = LinkedList<Int, LinkedListNode<Int>>()
list.append(5)
print(list.first?.value)
let someCustom = LinkedList<Int, GenericCustomNode<Int>>()
someCustom.append(15)
print(someCustom.first?.value)
let otherCustom = LinkedList<Int, NonGenericCustomNode>()
otherCustom.append(2)
print(otherCustom.first?.value)
Output:
Optional(5)
Optional(15)
Optional(2)
You will need to define a protocol with an associated type:
protocol Node: class {
associatedtype Value
var value: Value {get set}
var next: Self? {get set}
var prev: Self? {get set}
init(value: Value)
}
final class BasicNode<Value>: Node {
var value: Value
var next: BasicNode<Value>?
weak var prev: BasicNode<Value>?
init(value: Value) {
self.value = value
}
}
final class CustomNode<Value>: Node {
// customize however you want
var value: Value
var next: BasicNode<Value>?
weak var prev: BasicNode<Value>?
init(value: Value) {
self.value = value
}
}
class LinkedList<N: Node> {
var first: N? = nil
var last: N? = nil
var count = 0
#discardableResult
func append(_ value: N.Value) -> N {
let new = N(value: value)
new.prev = last
last?.next = new
count += 1
last = new
if first == nil {
first = new
}
return new
}
}
However, this will require using your basic linked list in an annoying way all the time:
let list = LinkedList<BasicNode<Int>>()
Depending on how you need to customize the node, I would consider finding a way to customize the behavior in the LinkList class itself using dependency injection.

Swift 2 issue with a closure for groupBy collection

The code below is written in order to group journal publications by year of publication.
But I got the error "Cannot convert value of type '(Journal) -> Int' to expected argument type '(_) -> _'"
Here's the playground with a stripped down version of the real code for you to play around http://swiftlang.ng.bluemix.net/#/repl/1de81132cb2430962b248d2d6ff64922e2fe912b1480db6a7276c6a03047dd89
class Journal {
var releaseDate: Int = 0
static var journals = [Journal]()
class func groupedReduce<S: SequenceType, K: Hashable, U> (
source: S,
initial: U,
combine: (U, S.Generator.Element) -> U,
groupBy: (S.Generator.Element) -> K
)
-> [K:U]
{
var result: [K:U] = [:]
for element in source {
let key = groupBy(element)
result[key] = combine(result[key] ?? initial, element)
}
return result
}
class func groupBy() {
let byYear = { (journal: Journal) in
journal.releaseDate
}
let groupedJournals = groupedReduce(journals, initial: 0, combine:+, groupBy: byYear)
print("Grouped journals = \(groupedJournals)")
}
}
Journal.journals = [Journal(), Journal(), Journal(), Journal()]
for j in Journal.journals {
j.releaseDate = 1
}
Journal.groupBy()
Your code is overly complicated. Below is a groupBy function that group elements of an array according to criteria of your choice. Playground
import Foundation
class Journal {
var releaseDate: Int = 0
init(_ releaseDate: Int) {
self.releaseDate = releaseDate
}
}
extension Array {
func groupBy<T: Hashable>(f: Element -> T) -> [T: [Element]] {
var results = [T: [Element]]()
for element in self {
let key = f(element)
if results[key] == nil {
results[key] = [Element]()
}
results[key]!.append(element)
}
return results
}
func groupBy2<T: Hashable>(f: Element -> T) -> [T: [Element]] {
return self.reduce([T: [Element]]()) { (var aggregate, element) in
let key = f(element)
if aggregate[key] == nil {
aggregate[key] = [Element]()
}
aggregate[key]!.append(element)
return aggregate
}
}
}
let journals = [Journal(2015), Journal(2016), Journal(2015), Journal(2014)]
let groupedJournals = journals.groupBy {
$0.releaseDate
}
print(groupedJournals)

Swift for-in loop with enumerate on custom Array2D class?

How would I go about implementing a custom enumerate function that makes something like this work (Swift 2):
for ((column, row), item) in Array2D.enumerate() { ... }
In my simple Array2D struct:
struct Array2D<T> : SequenceType {
let columns: Int
let rows: Int
private var array: Array<T?>
init(columns: Int, rows: Int) {
self.columns = columns
self.rows = rows
array = Array(count: rows*columns, repeatedValue: nil)
}
subscript(column: Int, row: Int) -> T? {
get {
return array[columns*row + column]
}
set {
array[columns*row + column] = newValue
}
}
func generate() -> AnyGenerator<T?> {
var column = 0
var row = 0
return anyGenerator() {
guard row < self.rows else {
return nil
}
let item = self[column, row]
if ++column == self.columns {
column = 0
++row
}
return item
}
}
}
I couldn't find any good explanation on implementing an enumerate function in Swift
The enumerate() function in Swift returns integers starting from 0 for the first part of its tuple. Those have nothing to do with the sequence you're enumerating over. So, for instance, this won't work:
let word = "hello".characters
for (index, letter) in word.enumerate() {
print(word[index])
}
Because the indices of a characterView are String.Indexs.
So there are several ways to get what you're going for. The first is to just overload enumerate() for your struct. Again, there are a few days you could do this. First off, how about a function that uses your own generator, and uses its own logic to figure out the coordinates. This could work:
func enumerate() -> AnyGenerator<((Int, Int), T?)> {
let g = self.generate()
var coord = -1
return anyGenerator {
g.next().map { ((++coord % self.columns, coord / self.columns), $0) }
}
}
But you're duplicating code there, especially from your generate method. Seeing you're already using coordinates to return each element, why not just have your enumerate method be the default, and your generate method call on that. Something like this:
// Original generate method, now returns the coords it used
func enumerate() -> AnyGenerator<((Int, Int), T?)> {
var column = 0
var row = 0
return anyGenerator() {
guard row < self.rows else {
return nil
}
let item = self[column, row]
if ++column == self.columns {
column = 0
++row
}
return ((column, row), item)
}
}
// uses enumerate, ignores coords
func generate() -> AnyGenerator<T?> {
let g = self.enumerate()
return anyGenerator {
g.next().map { $1 }
}
}
If you wanted to go a little overboard, you could write an enumerate function that enumerates the specific indices of its base. Call it specEnumerate:
public struct SpecEnumerateGen<Base : CollectionType> : GeneratorType {
private var eG: Base.Generator
private let sI: Base.Index
private var i : Base.Index?
public mutating func next() -> (Base.Index, Base.Generator.Element)? {
i?._successorInPlace() ?? {self.i = self.sI}()
return eG.next().map { (i!, $0) }
}
private init(g: Base.Generator, i: Base.Index) {
self.eG = g
self.sI = i
self.i = nil
}
}
public struct SpecEnumerateSeq<Base : CollectionType> : SequenceType {
private let col: Base
public func generate() -> SpecEnumerateGen<Base> {
return SpecEnumerateGen(g: col.generate(), i: col.startIndex)
}
}
public extension CollectionType {
func specEnumerate() -> SpecEnumerateSeq<Self> {
return SpecEnumerateSeq(col: self)
}
}
With this function, this would work:
let word = "hello".characters
for (index, letter) in word.specEnumerate() {
print(word[index])
}
But your matrix struct is still a SequenceType, with no specific indices. For that, you'll have to implement your own MatrixIndex:
public struct MatrixIndex: BidirectionalIndexType {
public let x, y : Int
private let columns: Int
public func successor() -> MatrixIndex {
return (x + 1 == columns) ?
MatrixIndex(x: 0, y: y + 1, columns: columns) :
MatrixIndex(x: x + 1, y: y, columns: columns)
}
public func predecessor() -> MatrixIndex {
return (x == 0) ?
MatrixIndex(x: columns - 1, y: y - 1, columns: columns) :
MatrixIndex(x: x - 1, y: y, columns: columns)
}
}
public func == (lhs: MatrixIndex, rhs: MatrixIndex) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
extension MatrixIndex : CustomDebugStringConvertible {
public var debugDescription: String {
return "\(x), \(y)"
}
}
extension MatrixIndex: RandomAccessIndexType {
public func advancedBy(n: Int) -> MatrixIndex {
let total = (y * columns) + x + n
return MatrixIndex(x: total % columns, y: total / columns, columns: columns)
}
public func distanceTo(other: MatrixIndex) -> Int {
return (other.x - x) + (other.y - y) * columns
}
}
Right. Now you'll need another matrix struct:
public struct Matrix2D<T> : MutableCollectionType {
public var contents: [[T]]
public subscript(index: MatrixIndex) -> T {
get {
return contents[index.y][index.x]
} set {
self.contents[index.y][index.x] = newValue
}
}
public var count: Int { return contents[0].count * contents.count }
public var startIndex: MatrixIndex {
return MatrixIndex(x: 0, y: 0, columns: contents[0].count)
}
public var endIndex: MatrixIndex {
return MatrixIndex(x: 0, y: contents.endIndex, columns: contents[0].count)
}
}
Right. So now, after all of that, this works:
let myMatrix = Matrix2D(contents: [[1, 2], [3, 4]])
for (coordinate, value) in myMatrix.specEnumerate() {
value == myMatrix[coordinate] // True every time
}
It might suffice defining your own enumerate taking advantage of the one you already have:
func enumerate() -> AnyGenerator<((Int, Int), T?)> {
var index = 0
var g = array.generate()
return anyGenerator() {
if let item = g.next() {
let column = index % self.columns
let row = index / self.columns
++index
return ((column, row) , item)
}
return nil
}
}
Notice in this case you could avoid conforming to SequenceType since I use generate from the private array. Anyway it could be consistent to do so.
Here is how then you could use it:
var a2d = Array2D<Int>(columns: 2, rows: 4)
a2d[0,1] = 4
for ((column, row), item) in a2d.enumerate() {
print ("[\(column) : \(row)] = \(item)")
}
Hope this helps