import UIKit // testing examples let beforeTxt = """ 1100111 1100111 1100111 1100111 1100110 1100110 1100110 1100110 1100110 1100110 1100110 1100110 1111110 0000000 """ let smallrc01 = """ 00000000000000000000000000000000 01111111110000000111111110000000 01110001111000001111001111000000 01110000111000001110000111000000 01110001111000001110000000000000 01111111110000001110000000000000 01110111100000001110000111000000 01110011110011101111001111011100 01110001111011100111111110011100 00000000000000000000000000000000 """ let rc01 = """ 00000000000000000000000000000000000000000000000000000000000 01111111111111111100000000000000000001111111111111000000000 01111111111111111110000000000000001111111111111111000000000 01111111111111111111000000000000111111111111111111000000000 01111111100000111111100000000001111111111111111111000000000 00011111100000111111100000000011111110000000111111000000000 00011111100000111111100000000111111100000000000000000000000 00011111111111111111000000000111111100000000000000000000000 00011111111111111110000000000111111100000000000000000000000 00011111111111111111000000000111111100000000000000000000000 00011111100000111111100000000111111100000000000000000000000 00011111100000111111100000000111111100000000000000000000000 00011111100000111111100000000011111110000000111111000000000 01111111100000111111100000000001111111111111111111000000000 01111111100000111111101111110000111111111111111111011111100 01111111100000111111101111110000001111111111111111011111100 01111111100000111111101111110000000001111111111111011111100 00000000000000000000000000000000000000000000000000000000000 """ // Zhang-Suen thinning algorithm in Swift /// function to thin the image func zhangSuen(image: inout [[Int]]) -> [[Int]] { // array of x, y position where need to changed to be white var changing1, changing2: [(Int, Int)] repeat { // set to empty array changing1 = [] changing2 = [] // Step 1 // loop through row of image for y in 1.. [[Int]] { // reference: https://stackoverflow.com/questions/28611336/how-to-convert-a-string-numeric-in-a-int-array-in-swift // map through each char of input String to convert to Int return binstring.split(separator: "\n").map {$0.compactMap{$0.wholeNumberValue}} } /// function to convert 2D Int array of 1/0 into multiline String of ‘#’ and ‘.’ func toTxt(intmatrix: [[Int]]) -> String { // map through each array of parent array and // map through element of child array and convert to '#' when 1 and to '.' when 0 return intmatrix.map {$0.map { $0 == 1 ? "#" : "."}.joined(separator: "")}.joined(separator: "\n") } /// function to get neighbours of P1 = [P2,P3,P4,P5,P6,P7,P8,P9] func neighbours(x: Int, y: Int, image: [[Int]]) -> [Int] { let i = image // set x, y positions of P1 neighbours let x1 = x+1, y1 = y-1, x_1 = x-1, y_1 = y+1 // return neighbours of P1 return [i[y1][x], i[y1][x1], i[y][x1], i[y_1][x1], // P2,P3,P4,P5 i[y_1][x], i[y_1][x_1], i[y][x_1], i[y1][x_1]] // P6,P7,P8,P9 } /// function to get the number of transitions from white to black, (0 -> 1) in the sequence P2,P3,P4,P5,P6,P7,P8,P9,P2. func transitions(neighbours: inout [Int]) -> Int { // add P2 at the end of neighbours array let n = neighbours + [neighbours[0]] var result = 0 // reference: https://www.marcosantadev.com/arrayslice-in-swift/ // compare between each element of neightbour and next element of the element to check if the transition is 0 -> 1 for (n1, n2) in zip(n, n.suffix(n.count - 1)) { // if the pattern matches, increament result to 1 if (n1, n2) == (0, 1) { result += 1 } } // return number of transitions from 0 to 1 return result } // run testing // array of test examples let testCases: [String] = [beforeTxt, smallrc01, rc01] for picture in testCases { // convert string to 2D Int array var image = intarray(binstring: picture) // print the result print("\nFrom:\n\(toTxt(intmatrix: image))") // run through Zhang-Suen thinning algorithm let after = zhangSuen(image: &image) // print the result print("\nTo thinned:\n\(toTxt(intmatrix: after))") }