Swift 3 conversion - 'predecessor()' is unavailable - swift

I am getting the above error. So how do we convert the following codes to swift 3 compatible?
let charactersAreInCorrectState = { () -> Bool in
let previousContext = self.textDocumentProxy.documentContextBeforeInput
if previousContext == nil || (previousContext!).characters.count < 3 {
return false
}
var index = previousContext!.endIndex
index = index.predecessor()
if previousContext![index] != " " {
return false
}

Related

How to pick First and Last number from String Swift

i want to get First and Last number from dynamic string.
String could be any number like below.
"1-3,28-30,55" ==> Output is 1 & 55
"104-105,131-132,157" ==> Output is 104 & 157
"188,192,194" ==> Output is 188 & 194
"202" ==> Output is 202 & 0
"204-206,208-212,215-220" Output is 204 & 220
OBJECT
class PalletRangeObject: NSObject {
var start: Int = 0
var end: Int = 0
var strRange: String = ""
init(start: Int, end: Int, range: String) {
self.start = start
self.end = end
self.strRange = range
}
}
For above achievement i have tried below code but in some cases it's not working.
for i in 0..<self.arrPalletRange.count {
let objPlRange = self.arrPalletRange[i]
if !objPlRange.strRange.isEmpty {
var nStart = 0
var nEnd = 0
let pointsArr = objPlRange.strRange.components(separatedBy: ",")
for i in 0..<pointsArr.count {
let arr = pointsArr[i].components(separatedBy: "-")
let newData = arr.map { Int($0)!}
if newData.count == 1 {
if nStart == 0 {
nStart = Int(newData.first ?? 0)
continue
}
nEnd = Int(newData.first ?? 0)
continue
}
else {
if nStart == 0 {
nStart = Int(newData.first ?? 0)
continue
}
nEnd = Int(newData.last ?? 0)
}
}
objPlRange.start = nStart
objPlRange.end = nEnd
}
}
Can anyone please guide me to achieve this.
Thanks in advance
It doesn't have to be that complicated. You seem to just want to get the first and last substring separated by either , or -.
You can use components(separatedBy:)
for i in 0..<self.arrPalletRange.count {
let objPlRange = self.arrPalletRange[i]
let allComponents = objPlRange.strRange.components(separatedBy: CharacterSet([",", "-"]))
if let firstComponent = allComponents.first,
let firstComponentInt = Int(firstComponent),
let lastComponent = allComponents.last,
let lastComponentInt = Int(lastComponentInt) {
objPlRange.start = firstComponentInt
objPlRange.end = lastComponentInt
} else {
// the string is empty, or the values are not valid integers
}
}
Alternatively, you can find the first and last index of a - or ,, and cut the string at those positions. This avoids creating the array of all components, since you don't need most of them.
for i in 0..<self.arrPalletRange.count {
let objPlRange = self.arrPalletRange[i]
let firstIndex = objPlRange.strRange.firstIndex(where: { $0 == "-" || $0 == "," }) ?? objPlRange.strRange.endIndex
let lastIndex = objPlRange.strRange.lastIndex(where: { $0 == "-" || $0 == "," }) ?? objPlRange.strRange.startIndex
if let firstComponentInt = Int(objPlRange.strRange[..<firstIndex])
let lastComponentInt = Int(lastComponentInt[lastIndex...]) {
objPlRange.start = firstComponentInt
objPlRange.end = lastComponentInt
} else {
// the string is empty, or the values are not valid integers
}
}
I would use firstIndex and lastIndex to find non-numerical characters and then use prefix and suffix to extract the values.
Here is a function that returns the first and last int as a tuple
func firstAndLast(_ string: String) -> (Int, Int) {
guard let start = string.firstIndex(where: { !$0.isNumber }) else {
return string.isEmpty ? (0, 0) : (Int(string) ?? 0, 0)
}
guard let end = string.lastIndex(where: { !$0.isNumber }) else {
return (0, 0)
}
return (Int(string.prefix(upTo: start)) ?? 0, Int(string.suffix(from: string.index(end, offsetBy: 1))) ?? 0)
}
This is a very simple code that you can use to achieve that.
For first Number
func findFirst(number: String) -> String{
guard number != "" else {return ""}
var firstNumber = ""
for i in number{
if i.isNumber{
firstNumber.append(i)
}else{
return firstNumber
}
}
return firstNumber
}
This is for the second number
func findLast(number: String) -> String{
guard number != "" else {return ""}
var firstNumber = ""
for i in number.reversed(){
if i.isNumber{
firstNumber.append(i)
}else{
return firstNumber
}
}
return firstNumber
}
Sorry if I didn't understand your question properly, but as per my understanding here is the simplest code I can give you
let string = "2A4-206,208-212,215-220"
let numbers = string.components(separatedBy: [",","-"]).filter({ string in
if let _ = Int(string) {
return true
} else {
return false
}
})
if numbers.count == 0 {
print("Start: 0, End: 0")
} else if let first = Int(numbers.first ?? ""), numbers.count == 1 {
print("Start: \(first), End: 0")
} else if let first = Int(numbers.first ?? ""), let last = Int(numbers.last ?? "") {
print("Start: \(first), End: \(last)")
}
You can add this code in function and replace print statement with return block

What is the swift way of converting this string into PGN notation?

I have the following string
let a:String = "r0bqkb0r/pppppppp/00n00n00/00000000/000P0000/0000B000/PPP0PPPP/RN0QKBNR/"
and want to convert this to PGN notation so the final result should be
result = "r1bqkb1r/pppppppp/2n2n2/8/3P4/4B3/PPP1PPPP/RN1QKBNR/"
The PGN notation converts the zeros to counts found. Normally in python, I would just use
import chess.pgn
Before deep diving into python library, is there is a succinct and 'Swift' way to do this?
Here is a solution using reduce and a separate counter
Update, rewrote it as an extension to String
extension String {
func pgpNotation() -> String {
var zeroCounter = 0
var result = self.reduce(into: "") {
if $1 == "0" {
zeroCounter += 1
return
}
if zeroCounter > 0 {
$0.append("\(zeroCounter)")
zeroCounter = 0
}
$0.append($1)
}
if zeroCounter > 0 { result.append("\(zeroCounter)")}
return result
}
}
Examples
let x = "r00d00"
print(x.pgpNotation())
let a:String = "r0bqkb0r/pppppppp/00n00n00/00000000/000P0000/0000B000/PPP0PPPP/RN0QKBNR/"
print(a.pgpNotation())
r2d2
r1bqkb1r/pppppppp/2n2n2/8/3P4/4B3/PPP1PPPP/RN1QKBNR/
There is no direct function for that but I just created a program for fun. You can check this out:-
let str = "r0bqkb0r/pppppppp/00n00n00/00000000/000P0000/0000B000/PPP0PPPP/RN0QKBNR/"
var newStr = ""
var flag = 0
// Do any additional setup after loading the view.
for char in str {
if flag == 0 {
if char == "0" {
flag += 1
}
else {
newStr.append(char)
}
}
else {
if char == "0" {
flag += 1
}
else {
newStr.append("\(flag)")
flag = 0
if char == "0" {
flag += 1
}
else {
newStr.append(char)
}
}
}
}
print(newStr)
There doesn't exist any direct method to get the pgn notation String. You can use a forEach(_:) instead, i.e.
let a = "r0bqkb0r/pppppppp/00n00n00/00000000/000P0000/0000B000/PPP0PPPP/RN0QKBNR/"
var result = ""
var count = 0
a.forEach {
if $0 == "0" {
count += 1
} else {
if count != 0 {
result.append("\(count)")
count = 0
}
result.append($0)
}
}
print(result) //r1bqkb1r/pppppppp/2n2n2/8/3P4/4B3/PPP1PPPP/RN1QKBNR/
With a simple regex and a loop (just to propose an original solution):
let a = "r0bqkb0r/pppppppp/00n00n00/00000000/000P0000/0000B000/PPP0PPPP/RN0QKBNR/"
extension String {
var chessPGN : String {
var result = self
let regex = try! NSRegularExpression(pattern: "0+")
while let match = regex.matches(in: result, range: .init(location: 0, length: result.count)).first {
if let stringRange = Range(match.range , in: result) {
result.replaceSubrange(stringRange, with: match.range.length.description)
}
}
return result
}
}
print(a.chessPGN) // r1bqkb1r/pppppppp/2n2n2/8/3P4/4B3/PPP1PPPP/RN1QKBNR/
EDIT: A version calling only once the regex
extension String {
var chessPGN : String {
var result = self
let regex = try! NSRegularExpression(pattern: "0+")
for match in regex.matches(in: result, range: .init(location: 0, length: result.count)).sorted(by: { $0.range.location > $1.range.location }) {
if let stringRange = Range(match.range , in: result) {
result.replaceSubrange(stringRange, with: match.range.length.description)
}
}
return result
}
}

Practical number algorithm too slow

I am trying to write a program to find the practical numbers, from an input from 1 to n.
Practical numbers : https://en.wikipedia.org/wiki/Practical_number
My code is running correctly but it is extremely slow - takes over 20 minutes when it should take 10 seconds. This happens when calculating numbers around 50 - it gets stuck at 44.
It is written in Swift
import Foundation
func getInteger() -> Int {
var firstNum:Int = 0
while true {
// get value from user. Using optional input since readLine returns an optional string.
let input = readLine()
// ensure string is not nil
if let unwrappedInput = input {
if let unwrappedInt = Int(unwrappedInput) {
firstNum = unwrappedInt
break
}
else { // the input doesn't convert into an int
print("`\(unwrappedInput)` is not an integer. Please enter an integer")
}
}
else { // did not enter anything
print("Please enter an integer")
}
}
return firstNum
}
func addOne(signArray: [Int]) -> [Int] { // finds the combinations
var signArray2 = [Int]()
for i in 0...signArray.count-1 {
signArray2.append (signArray[i])
}
for i in 0...signArray2.count-1 {
if signArray2[i] == 1 {
signArray2[i] = 0
}
else {
signArray2[i] = 1
break
}
}
return signArray2
}
func signEval (signArray: [Int], divArray: [Int], inNum: Int) -> Bool {// changes 2nd
var counts = 0
for i in 0...divArray.count-1 {
if signArray[i] == 0 {
counts = divArray[i] + counts }
if counts == inNum {
return true
}
}
return false
}
print("Please enter a number to find the summable numbers up to that number:")
var input2 = getInteger()// if num = 1 print 1 if num = 2 print 1 and 2 else print >2 1, 2
var inNum = 0
var numHalf = 0.0
var numRound = 0.0
var numCheck = false
var numCheck2 = false
var numQuarter = 0.0
var numSixth = 0.0
var divArray:[Int] = []
var theirArray = [Int]()
var signArray = [Int]()// array of 0s and 1s
var summableArray:[Int] = [1,2] // need to check if num is bigger than 2!
for input in 1...input2 {
numHalf = Double (input) / 2.0
numRound = round(numHalf)
if numRound == numHalf {
numCheck = true }
if input > 2 && numCheck == false { // odd numbers greater than one are not summable
}
else { // these are possible summable nums
numQuarter = Double (input) / 4.0
numRound = round(numQuarter)
if numRound == numQuarter {
numCheck = true
}
else {
numCheck = false
}
numSixth = Double(input) / 6.0
numRound = round(numSixth)
if numRound == numSixth {
numCheck2 = true }
else { numCheck2 = false}
if numCheck == true || numCheck2 == true {
theirArray = []
divArray = []
signArray = []
summableArray = []
for i in 1...input {
theirArray.append (i)
}
for i in 1...input { // creates an array of all the diviors of inputted number
if input%i == 0 {
divArray.append (i)
}
}
for j in 1...divArray.count {//
signArray.append(0)
}
for i in 1...input{
let x: Int = Int(pow(Double(2),Double(input-1)))// int 2 to the power of input -1
var Boolcheck = false
for q in 1...x-1 { // i to 2^n -1 (sequence to check)
Boolcheck = (signEval(signArray: signArray, divArray: divArray, inNum: i))// checks
signArray = addOne(signArray: signArray)// adding the ones to the array
if Boolcheck == true {
summableArray.append(i)// creates array of mini summable numbers
break
}
}
if summableArray.count == input {
print ("\(input)")
}
}
}
}
}

Swift Dijkstra Algorithm Error (EXC_BAD_INSTRUCTION)

So I've built a swift playground that uses Dijkstra's algorithm to find the shortest route. However, I can't seem to manipulate my txt file so that my function will work in every case. It only works for a select few pathways. Whenever I map out a pathway I believe should work, it responds with: Execution was interrupted, reason: EXC_BAD_INSTRUCTION(code=EXC_I386_INVOP, subcode=0x0).
How can I manipulate my txt file or my function/file manipulation to take my txt file input? (Where error occurred is marked -- near the bottom)
Usually the error occurs when trying to build a route backwards.
Ex: a1 to a3 works
Ex: a3 to a1 does not work
Code:
import Foundation
// Extensions
extension Array {
func each<U>(closure:(Element)->U?)->U? {
for i in self {
let returnVal = closure(i)
if (returnVal != nil) { return returnVal }
}
return nil
}
}
extension Int {
func times(closure:(Int)->Void) {
for i in 0..<self { closure(i) }
}
}
// Structs
struct Edge {
var wt: Double
var desV: Room
}
struct Graph { var vertices:[Room] }
// Room Class
class Room: Hashable {
var name: String?
var neighbors: [Edge] = []
var hashValue: Int {
get { return name!.hashValue }
}
init(){}
convenience init(name:String) {
self.init()
self.name = name
}
func distanceToRoom(targetRoom:Room) -> Edge? {
return self.neighbors.each({ (edge:Edge) -> Edge? in
if (edge.desV == targetRoom) {
return edge
}
return nil
})
}
}
// Functions
func == (lhs:Room, rhs:Room) -> Bool { return lhs.hashValue == rhs.hashValue }
func say( a:String ) { print( a, terminator:"") }
func dijkstra(graph:Graph, target:Room) -> [Room:Room] {
var queue = graph.vertices
var distances:[Room:Double] = [:]
var previousPaths:[Room:Room] = [:]
let currentRoom:Room = queue[0]
queue.each {(element:Room) -> Void? in
distances[element] = Double.infinity
previousPaths[element] = nil
return nil
}
distances[currentRoom] = 0
while (queue.count > 0) {
var closestNode:Room? = nil
let wt:Double = Double.infinity
queue.each({ (Room:Room) -> Void? in
if (closestNode == nil || wt < distances[Room]!) {
closestNode = Room
}
return nil
})
if (closestNode! == target) {
return previousPaths
}
let nodeIndex:Int? = queue.indexOf(closestNode!)
queue.removeAtIndex(nodeIndex!)
if (closestNode?.neighbors != nil && closestNode?.neighbors.count > 0) {
closestNode?.neighbors.each({(neighbor:Edge) -> Void? in
let wt = distances[closestNode!]! + closestNode!.distanceToRoom(neighbor.desV)!.wt
if wt < distances[neighbor.desV] {
distances[neighbor.desV] = wt
previousPaths[neighbor.desV] = closestNode!
}
return nil
})
}
}
return previousPaths
}
// File Management
//let url = NSURL(string:"file:///Users/caleb/Documents/Xcode/CRHS/CRHS/dtb.txt")!
let url = NSURL(string: "file:///Users/caleb/Desktop/rooms.txt")!
let data = NSData(contentsOfURL: url)
let sdata = String(data: data!, encoding: NSUTF8StringEncoding)
let dataArray = sdata!.characters.split{$0 == "\n"}.map(String.init)
var rooms = [String:Room]()
print("data:\n-------")
for i in 0 ..< dataArray.count {
let conn = dataArray[i].characters.split{$0 == "\t"}.map(String.init)
var room1: Room
if ( rooms[conn[0]] == nil ) {
room1 = Room(name: conn[0])
} else {
room1 = rooms[conn[0]]!
}
let room2 = Room(name: conn[2])
let edwt = (conn[1] as NSString).doubleValue
var edge = Edge(wt: edwt, desV: room2)
if room1.neighbors.count == 0 {
room1.neighbors = [ edge ]
} else {
var found: Bool = false
for e in room1.neighbors {
if ( e.desV.name == edge.desV.name ) {
found = true
}
}
if ( found == false ) {
room1.neighbors.append(edge)
}
}
rooms[conn[0]] = room1
}
for (nam,room) in rooms {
print(nam)
print("----")
for n in room.neighbors {
if let un = n.desV.name {
print( un, terminator: " weight: ")
}
print( n.wt )
}
print("\n")
}
var namessofrooms = rooms.map { $0.0 }
var roomsofrooms = rooms.map { $0.1 }
print("Rooms:")
print(rooms)
print("-------\n")
// Calculating
var source = rooms["a1"]!
var target = rooms["a4"]!
roomsofrooms.append(source)
var reversedRooms: Array = roomsofrooms.reverse()
reversedRooms.append(target)
var graph = Graph(vertices: reversedRooms)
var paths = dijkstra(graph, target: target)
var pathVertices:[Room] = [target]
var child = target
while (child != source) {
print(child.name)
print(":::::")
child = paths[child]! //Error occurs here
print(child.name)
pathVertices.append(child)
}
var pathString:[String] = pathVertices.reverse().map { (Room:Room) -> String in
return Room.name!
}
print("solution:\n-------")
print(pathString)
Below is the file I input:
a1 1 a2
a2 1 a3
a3 1 a4
If I input the following file the code above will not work:
a1 1 a2
a2 1 a3
a3 1 a4
a4 1 a5
(Update: File Map Clarification)
First column is the first room, second is the weight between the rooms, third is the room connected to the first.

NilLiteralConvertible in Property setter

In swift I have this:
///3.5.1.8 Range is ± 32,576 FPM, FPM of 32640 means max. Also can be invalid (nil)
var vVelcotiy: Int? {
get {
let ret : Int16 = decode12Bit2sCompliment(bytes[15], bytes[16], useEntireFirstByte: false)
return Int(ret * 64);
}
set {
if (bytes[15] == 8 && bytes[16] == 0) {
return nil
}
if let n = newValue {
let nv = n / 64
bytes[15] = (bytes[15] & 0xF0) | (UInt8(nv) >> 8)
bytes[16] = UInt8(nv)
} else {
bytes[15] = (bytes[15] & 0xF0) | 0xF8
bytes[16] = 0x00
}
}
}
I'm getting an error of type '()' does not conform to protocol 'NilLiteralConvertible' but I've declared my property as optional so I'm confused.
I'm hoping to be able to do:
var a : vVelocity = nil
Reading rintaro's answer and taking my comment into consideration, I think you've misplaced the first check in the setter, it looks like it belongs in the getter instead:
var vVelcotiy: Int? {
get {
if (bytes[15] == 8 && bytes[16] == 0) {
return nil
}
let ret : Int16 = decode12Bit2sCompliment(bytes[15], bytes[16], useEntireFirstByte: false)
return Int(ret * 64);
}
set {
if let n = newValue {
let nv = n / 64
bytes[15] = (bytes[15] & 0xF0) | (UInt8(nv) >> 8)
bytes[16] = UInt8(nv)
} else {
bytes[15] = (bytes[15] & 0xF0) | 0xF8
bytes[16] = 0x00
}
}
}
Now your getter has a possibility of returning nil, and your setter doesn't depend on the existing value.
The error is here:
set {
if (bytes[15] == 8 && bytes[16] == 0) {
return nil // <--- HERE
}
You cannot return anything from set { }. If you want to break, just return instead.
set {
if (bytes[15] == 8 && bytes[16] == 0) {
return
}