skip to Main Content

Convert this below array into matrix
Array

let ptsArray = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]

Matrix

    0    1   2   3   4   5
    6    7   8   9   10  11
    12   13  14  15  16  17

To find adjacent points in uniderectional like an below image

enter image description here

Expected output

(0,1) (0,6)
(1,2) (1,7)
(2,3) (2,8)
(3,4) (3,9)
(4,5) (4,10)
(5,11)

(6,7)  (6,12)
(7,8)  (7,13)
(8,9)  (8,14)
(9,10) (9,15)
(10,11) (10,16)
(11,17)

(12,13) 
(13,14)
(14,15)
(15,16)
(16,17)

My failed approach

 for i in 0..<pointsArray.count-1{
        if (i+1)%6 == 0 && i != 0{
            print("Connection ((i),(i+6))")
            nodesArray[i].addConnection(to: nodesArray[i+6], bidirectional: true, weight: 1)
        }
        if i>=pointsArray.count-6{
            print("Connection ((i),(i+1))")
            nodesArray[i].addConnection(to: nodesArray[i+1], bidirectional: true, weight: 1)
        }
        else{
            print("Connection ((i),(i+1)) ((i),(i+6))")
            nodesArray[i].addConnection(to: nodesArray[i+1], bidirectional: true, weight: 1)
            nodesArray[i].addConnection(to: nodesArray[i+6], bidirectional: true, weight: 1)
        }
    }

Output:

Connection (0,1) (0,6)
Connection (1,2) (1,7)
Connection (2,3) (2,8)
Connection (3,4) (3,9)
Connection (4,5) (4,10)
Connection (5,11)
Connection (5,6) (5,11)
Connection (6,7) (6,12)
Connection (7,8) (7,13)
Connection (8,9) (8,14)
Connection (9,10) (9,15)
Connection (10,11) (10,16)
Connection (11,17)
Connection (11,12) (11,17)
Connection (12,13)
Connection (13,14)
Connection (14,15)
Connection (15,16)
Connection (16,17)

2

Answers


  1. In the desired output, I guess that it’s missing (9,15), (10,11), (10,16) and that (10,15) isn’t valid.

    If we think about your desired output, we notice something.
    Let’s name width = 6, it’s the "width" of your matrix.

    We see the pattern:
    (value, value + 1), (value, value + width)
    With some excluded tests: does (value + width) exists ? And we are not at the end of the width.

    Let’s, with a little reduce method:

    let ptsArray = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
    
    let width = 6
    let tuples = ptsArray.indices.reduce(into: [(Int, Int)]()) { partialResult, anIndex in
        if ptsArray.count > anIndex.advanced(by: 1) && anIndex % width != width - 1 {
            let newValue = (ptsArray[anIndex], ptsArray[anIndex.advanced(by: 1)])
            print(newValue)
            partialResult.append(newValue)
        }
        if ptsArray.count > anIndex.advanced(by: width) {
            let newValue = (ptsArray[anIndex], ptsArray[anIndex.advanced(by: width)])
            print(newValue)
            partialResult.append(newValue)
        }
        return
    }
    print(tuples)
    

    I used "index", because in fact, points are in order here, but it could be any value, no? So let’s use the index instead.

    So, with something a little more generic:

    extension Array {
        func coupling(with width: Int) -> [(Element, Element)] {
            let couples = indices.reduce(into: [(Element, Element)]()) { partialResult, anIndex in
                if count > anIndex.advanced(by: 1) && anIndex % width != width - 1 {
                    let newValue = (self[anIndex], self[anIndex.advanced(by: 1)])
                    partialResult.append(newValue)
                }
                if count > anIndex.advanced(by: width) {
                    let newValue = (self[anIndex], self[anIndex.advanced(by: width)])
                    partialResult.append(newValue)
                }
                return
            }
            return couples
        }
    }
    

    Use:

    let ptsArray = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
    let tuples2 = ptsArray. coupling(with: width)
    print(tuples2)
    
    let lettersArray = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P", "Q", "R"]
    let tuples3 = lettersArray. coupling(with: width)
    print(tuples3)
    
    Login or Signup to reply.
  2. Another approach – convert your ptsArray into a 2-D matrix:

    var matrix: [[Int]] = []
    
    let numCols: Int = 6
    var numRows: Int = 0
    
    let ptsArray: [Int] = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
        
    for i in stride(from: 0, to: ptsArray.count, by: numCols) {
        // make sure we don't exceed the array limit
        if ptsArray.count >= i+numCols {
            matrix.append(Array(ptsArray[i..<i+numCols]))
        }
    }
    
    numRows = matrix.count
    

    You can now get the right and down values (if they exist) like this:

    func getPair2D(_ n: Int) -> (Int?, Int?) {
        
        let thisRow = n / numCols
        let thisCol = n % numCols
        
        let numToRight = thisCol < numCols-1 ? matrix[thisRow][thisCol+1] : nil
        let numToDown = thisRow < numRows-1 ? matrix[thisRow+1][thisCol] : nil
        
        return (numToRight, numToDown)
        
    }
    

    and this will print out the results:

    for i in 0..<ptsArray.count {
            
        let (n1, n2) = getPair2D(i)
        var str = ""
        if let n1 = n1 {
            str += "((i), (n1))"
        }
        if let n2 = n2 {
            if !str.isEmpty { str += " " }
            str += "((i), (n2))"
        }
    
        print(str)
            
    }
    

    Here’s a simple view controller that let’s you tap any number to show the "right and down" matches:

    class MatrixVC: UIViewController {
        
        var matrix: [[Int]] = []
    
        var views: [UIView] = []
        
        let numCols: Int = 6
        var numRows: Int = 0
    
        override func viewDidLoad() {
            super.viewDidLoad()
            
            let ptsArray: [Int] = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
    
            for i in stride(from: 0, to: ptsArray.count, by: numCols) {
                if ptsArray.count >= i+numCols {
                    matrix.append(Array(ptsArray[i..<i+numCols]))
                }
            }
            
            numRows = matrix.count
            
            let oStack: UIStackView = {
                let v = UIStackView()
                v.axis = .vertical
                v.distribution = .fillEqually
                v.spacing = 2
                return v
            }()
            
            var n = 0
            for r in 0..<numRows {
                let rStack: UIStackView = {
                    let v = UIStackView()
                    v.axis = .horizontal
                    v.distribution = .fillEqually
                    v.spacing = 2
                    return v
                }()
                for c in 0..<numCols {
                    let v = UILabel()
                    v.textAlignment = .center
                    v.text = "(ptsArray[n])"
                    v.isUserInteractionEnabled = true
                    let t = UITapGestureRecognizer(target: self, action: #selector(gotTap(_:)))
                    v.addGestureRecognizer(t)
                    rStack.addArrangedSubview(v)
                    views.append(v)
                    if c < numCols-1 {
                        let iv = UIImageView(image: UIImage(systemName: "arrow.right"))
                        rStack.addArrangedSubview(iv)
                    }
                    n += 1
                }
                oStack.addArrangedSubview(rStack)
                if r < numRows-1 {
                    let rStack: UIStackView = {
                        let v = UIStackView()
                        v.axis = .horizontal
                        v.distribution = .fillEqually
                        v.spacing = 2
                        return v
                    }()
                    for c in 0..<numCols {
                        let iv = UIImageView(image: UIImage(systemName: "arrow.down"))
                        rStack.addArrangedSubview(iv)
                        if c < numCols-1 {
                            let v = UIView()
                            rStack.addArrangedSubview(v)
                        }
                    }
                    oStack.addArrangedSubview(rStack)
                }
            }
        
            oStack.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(oStack)
    
            let g = view.safeAreaLayoutGuide
            NSLayoutConstraint.activate([
                
                oStack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
                oStack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),
                oStack.centerXAnchor.constraint(equalTo: g.centerXAnchor),
                oStack.centerYAnchor.constraint(equalTo: g.centerYAnchor),
                
            ])
    
        }
        
        @objc func gotTap(_ g: UITapGestureRecognizer) {
            
            guard let v = g.view as? UILabel,
                  let t = v.text,
                  let n = Int(t)
            else { return }
            
            // if the tapped label is yellow, let's just deselect all
            let deselecting: Bool = views[n].backgroundColor == .yellow
            
            views.forEach { $0.backgroundColor = .clear }
    
            if deselecting {
                return()
            }
            
            views[n].backgroundColor = .yellow
            
            let (n1, n2) = getPair2D(n)
            if let n1 = n1 {
                views[n1].backgroundColor = .yellow
            }
            if let n2 = n2 {
                views[n2].backgroundColor = .yellow
            }
    
        }
    
        func getPair2D(_ n: Int) -> (Int?, Int?) {
            
            let thisRow = n / numCols
            let thisCol = n % numCols
            
            let numToRight = thisCol < numCols-1 ? matrix[thisRow][thisCol+1] : nil
            let numToDown = thisRow < numRows-1 ? matrix[thisRow+1][thisCol] : nil
            
            return (numToRight, numToDown)
            
        }
        
    }
    

    It looks like this:

    enter image description here

    Tapping any number will highlight the pair:

    enter image description here

    enter image description here

    Tapping a "highlighted" number will "un-highlight" all numbers.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search