/** Implementation of the "atoi" function in Swift. This implementation is an exercise and should not be used in production, Swift has built-in types and functions that can do this sort of conversion. */ /// Parses the input string as a 32-bit integer. /// Returns `nil` if the input contains non-ASCII characters, or is not a valid number. func myAtoi(_ input: String) -> Int32? { /// The base ASCII code, where the numbers begin. let base = UInt8(48) /// This function will be applied to the number before the function returns. /// It's used to change the sign according to the input. var signfn: ((Int32) -> Int32) = { $0 } /// This will be updated as the input is parsed and returned from the function. /// It is an `Int` instead of an `Int32` because the value can extrapolate the maximum value /// that `Int32` can hold depending upon the input. /// We'll clamp this value before returning it as an `Int32`. var output: Int = 0 for (index, char) in input.enumerated() { /// We only work with ASCII characters, an input /// that contains non-ASCII characters is invalid. guard let ascii = char.asciiValue else { return nil } /// If the character is not a number. guard ascii >= base else { /// The only position where a non-number character /// is acceptable is in the first position (for the sign). guard index == 0 else { return nil } /// The only acceptable non-number character in the first /// position is ASCII code 45 (the minus sign). guard ascii == 45 else { return nil } /// Found the minus sign in front of the number string, /// set the sign function to multiply the number by -1. signfn = { $0 * -1 } continue } /// Compute the current digit by subtracting the base /// ASCII code from the current digit's ASCII code. let digit = Int(ascii - base) /// Since we're working with the decimal system, each time /// we find a new digit to the right, we multiply the /// current number by 10, then add the new digit to the result. output = (output * 10) + digit } /// The nested max/min ensures the final value /// lies between Int32.min and Int32.max. let clamped = Int32(max(min(output, Int(Int32.max)), Int(Int32.min))) /// Run signfn, which will multiply the number by -1 /// if a minus sign was found in the first position. return signfn(clamped) } myAtoi("0") == 0 myAtoi("123") == 123 myAtoi("2048") == 2048 myAtoi("-999") == -999 myAtoi("99999999999999") == Int32.max myAtoi("-🤡123") == nil