What's the best way to get updated Character by moving a given Integer - swift

Swift character is so hard to manipulate..
I have a simple request:
For a given string, I'd like to encode it with a "moving integer" for all the alphabetical digits.
For example: "abc", move 1: would become "bcd"; "ABC", move 1 -> "BCD".
One thing to note is, if after moving, the range it larger than "z" or "Z", it should loop back and calculate from "a" or "A" again. e.g "XYZ", move 1 -> "YZA"
This would be very easy to do in Java. But could anyone show me what would be the cleanest way to do it swift?
I've done something like:
let arr: [Character] = Array(s)
for i in arr {
let curAsciiValue = i.asciiValue!
var updatedVal = (curAsciiValue + UInt8(withRotationFactor))
if i >= "A" && i <= "Z" {
newAsciiVal = 65
updatedVal = updatedVal - 65 >= 26 ? 65 + (updatedVal - 65) % 26 : updatedVal
} else if i >= "a" && i <= "z" {
newAsciiVal = 97
updatedVal = updatedVal - 97 >= 26 ? 97 + (updatedVal - 97) % 26 : updatedVal
}
}
What should be best way to do this?

Better to bring all your logic together extending the Character type:
extension Character {
var isAlphabet: Bool { isLowercaseAlphabet || isUppercaseAlphabet }
var isLowercaseAlphabet: Bool { "a"..."z" ~= self }
var isUppercaseAlphabet: Bool { "A"..."Z" ~= self }
func rotateAlphabetLetter(_ factor: Int) -> Self? {
precondition(factor > 0, "rotation must be positive")
guard let asciiValue = asciiValue, isAlphabet else { return nil }
let addition = asciiValue + UInt8(factor % 26)
return .init(UnicodeScalar(addition > (isLowercaseAlphabet ? 122 : 90) ? addition - 26 : addition))
}
}
Character("a").rotateAlphabetLetter(2) // "c"
Character("A").rotateAlphabetLetter(2) // "C"
Character("j").rotateAlphabetLetter(2) // "l"
Character("J").rotateAlphabetLetter(2) // "L"
Character("z").rotateAlphabetLetter(2) // "b"
Character("Z").rotateAlphabetLetter(2) // "B"
Character("ç").rotateAlphabetLetter(2) // nil
Character("Ç").rotateAlphabetLetter(2) // nil
Expanding on that you can map your string elements using compactMap:
let string = "XYZ"
let rotatedAlphabetLetters = string.compactMap { $0.rotateAlphabetLetter(2) } // ["Z", "A", "B"]
And to convert the sequence of characters back to string:
extension Sequence where Element == Character {
var string: String { .init(self) }
}
let result = rotatedAlphabetLetters.string // "ZAB"
or simply in one liner:
let result = "XYZ".compactMap { $0.rotateAlphabetLetter(2) }.string // "ZAB"

Related

How to execute multiplications and/or divisions in the right order?

I am doing a simple calculator, but when performing the multiplication and division, my code doesn't make them a priority over plus and minus.
When doing -> 2 + 2 * 4, result = 16 instead of 10...
How to conform to the math logic inside my switch statement?
mutating func calculateTotal() -> Double {
var total: Double = 0
for (i, stringNumber) in stringNumbers.enumerated() {
if let number = Double(stringNumber) {
switch operators[i] {
case "+":
total += number
case "-":
total -= number
case "÷":
total /= number
case "×":
total *= number
default:
break
}
}
}
clear()
return total
}
Assuming you want a generalised and perhaps extensible algorithm for any arithmetic expression, the right way to do this is to use the Shunting Yard algorithm.
You have an input stream, which is the numbers and operators as the user typed them in and you have an output stream, which is the same numbers and operators but rearranged into reverse Polish notation. So, for example 2 + 2 * 4 would be transformed into 2 2 4 * + which is easily calculated by putting the numbers on a stack as you read them and applying the operators to the top items on the stack as you read them.
To do this the algorithm has an operator stack which can be visualised as a siding (hence "shunting yard") into which low priority operators are shunted until they are needed.
The general algorithm is
read an item from the input
if it is a number send it to the output
if the number is an operator then
while the operator on the top of the stack is of higher precedence than the operator you have pop the operator on the stack and send it to the output
push the operator you read from input onto the stack
repeat the above until the input is empty
pop all the operators on the stack into the output
So if you have 2 + 2 * 4 (NB top of the stack is on the left, bottom of the stack is on the right)
start:
input: 2 + 2 * 4
output: <empty>
stack: <empty>
step 1: send the 2 to output
input: + 2 * 4
output: 2
stack: <empty>
step 2: stack is empty so put + on the stack
input: 2 * 4
output: 2
stack: +
step 3: send the 2 to output
input: * 4
output: 2 2
stack: +
step 4: + is lower priority than * so just put * on the stack
input: 4
output: 2 2
stack: * +
step 5: Send 4 to output
input:
output: 2 2 4
stack: * +
step 6: Input is empty so pop the stack to output
input:
output: 2 2 4 * +
stack:
The Wikipedia entry I linked above has a more detailed description and an algorithm that can handle parentheses and function calls and is much more extensible.
For completeness, here is an implementation of my simplified version of the algorithm
enum Token: CustomStringConvertible
{
var description: String
{
switch self
{
case .number(let num):
return "\(num)"
case .op(let symbol):
return "\(symbol)"
}
}
case op(String)
case number(Int)
var precedence: Int
{
switch self
{
case .op(let symbol):
return Token.precedences[symbol] ?? -1
default:
return -1
}
}
var operation: (inout Stack<Int>) -> ()
{
switch self
{
case .op(let symbol):
return Token.operations[symbol]!
case .number(let value):
return { $0.push(value) }
}
}
static let precedences = [ "+" : 10, "-" : 10, "*" : 20, "/" : 20]
static let operations: [String : (inout Stack<Int>) -> ()] =
[
"+" : { $0.push($0.pop() + $0.pop()) },
"-" : { $0.push($0.pop() - $0.pop()) },
"*" : { $0.push($0.pop() * $0.pop()) },
"/" : { $0.push($0.pop() / $0.pop()) }
]
}
struct Stack<T>
{
var values: [T] = []
var isEmpty: Bool { return values.isEmpty }
mutating func push(_ n: T)
{
values.append(n)
}
mutating func pop() -> T
{
return values.removeLast()
}
func peek() -> T
{
return values.last!
}
}
func shuntingYard(input: [Token]) -> [Token]
{
var operatorStack = Stack<Token>()
var output: [Token] = []
for token in input
{
switch token
{
case .number:
output.append(token)
case .op:
while !operatorStack.isEmpty && operatorStack.peek().precedence >= token.precedence
{
output.append(operatorStack.pop())
}
operatorStack.push(token)
}
}
while !operatorStack.isEmpty
{
output.append(operatorStack.pop())
}
return output
}
let input: [Token] = [ .number(2), .op("+"), .number(2), .op("*"), .number(4)]
let output = shuntingYard(input: input)
print("\(output)")
var dataStack = Stack<Int>()
for token in output
{
token.operation(&dataStack)
}
print(dataStack.pop())
If you only have the four operations +, -, x, and ÷, you can do this by keeping track of a pendingOperand and pendingOperation whenever you encounter a + or -.
Then compute the pending operation when you encounter another + or -, or at the end of the calculation. Note that + or - computes the pending operation, but then immediately starts a new one.
I have modified your function to take the stringNumbers, operators, and initial values as input so that it could be tested independently in a Playground.
func calculateTotal(stringNumbers: [String], operators: [String], initial: Double) -> Double {
func performPendingOperation(operand: Double, operation: String, total: Double) -> Double {
switch operation {
case "+":
return operand + total
case "-":
return operand - total
default:
return total
}
}
var total = initial
var pendingOperand = 0.0
var pendingOperation = ""
for (i, stringNumber) in stringNumbers.enumerated() {
if let number = Double(stringNumber) {
switch operators[i] {
case "+":
total = performPendingOperation(operand: pendingOperand, operation: pendingOperation, total: total)
pendingOperand = total
pendingOperation = "+"
total = number
case "-":
total = performPendingOperation(operand: pendingOperand, operation: pendingOperation, total: total)
pendingOperand = total
pendingOperation = "-"
total = number
case "÷":
total /= number
case "×":
total *= number
default:
break
}
}
}
// Perform final pending operation if needed
total = performPendingOperation(operand: pendingOperand, operation: pendingOperation, total: total)
// clear()
return total
}
Tests:
// 4 + 3
calculateTotal(stringNumbers: ["3"], operators: ["+"], initial: 4)
7
// 4 × 3
calculateTotal(stringNumbers: ["3"], operators: ["×"], initial: 4)
12
// 2 + 2 × 4
calculateTotal(stringNumbers: ["2", "4"], operators: ["+", "×"], initial: 2)
10
// 2 × 2 + 4
calculateTotal(stringNumbers: ["2", "4"], operators: ["×", "+"], initial: 2)
8
// 17 - 2 × 3 + 10 + 7 ÷ 7
calculateTotal(stringNumbers: ["2", "3", "10", "7", "7"], operators: ["-", "×", "+", "+", "÷"], initial: 17)
22
First you have to search in the array to see if there is a ÷ or × sign.
Than you can just sum or subtract.
mutating func calculateTotal() -> Double {
var total: Double = 0
for (i, stringNumber) in stringNumbers.enumerated() {
if let number = Double(stringNumber) {
switch operators[i] {
case "÷":
total /= number
case "×":
total *= number
default:
break
}
//Remove the number from the array and make another for loop with the sum and subtract operations.
}
}
clear()
return total
}
This will work if you are not using complex numbers.
If you don't care speed, as it's running by a computer and you may use the machine way to handle it. Just pick one feasible calculate to do it and then repeat until every one is calculated.
Just for fun here. I use some stupid variable and function names.
func evaluate(_ values: [String]) -> String{
switch values[1] {
case "+": return String(Int(values[0])! + Int(values[2])!)
case "-": return String(Int(values[0])! - Int(values[2])!)
case "×": return String(Int(values[0])! * Int(values[2])!)
case "÷": return String(Int(values[0])! / Int(values[2])!)
default: break;
}
return "";
}
func oneTime(_ string: inout String, _ strings: [String]) throws{
if let first = try NSRegularExpression(pattern: "(\\d+)\\s*(\(strings.map{"\\\($0)"}.joined(separator: "|")))\\s*(\\d+)", options: []).firstMatch(in: string , options: [], range: NSMakeRange(0, string.count)) {
let tempResult = evaluate((1...3).map{ (string as NSString).substring(with: first.range(at: $0))})
string.replaceSubrange( Range(first.range(at: 0), in: string)! , with: tempResult)
}
}
func recursive(_ string: inout String, _ strings: [String]) throws{
var count : Int!
repeat{ count = string.count ; try oneTime(&string, strings)
} while (count != string.count)
}
func final(_ string: inout String, _ strings: [[String]]) throws -> String{
return try strings.reduce(into: string) { (result, signs) in
try recursive(&string, signs)
}}
var string = "17 - 23 + 10 + 7 ÷ 7"
try final(&string, [["×","÷"],["+","-"]])
print("result:" + string)
Using JeremyP method and the Shunting Yard algorithm was the way that worked for me, but I had some differences that had to do with the Operator Associativity(left or right priority) so I had to work with it and I developed the code, which is based on JeremyP answer but uses arrays.
First we have the array with the calculation in Strings, e.g.:
let testArray = ["10","+", "5", "*" , "4", "+" , "10", "+", "20", "/", "2"]
We use the function below to get the RPN version using the Shunting Yard algorithm.
func getRPNArray(calculationArray: [String]) -> [String]{
let c = calculationArray
var myRPNArray = [String]()
var operandArray = [String]()
for i in 0...c.count - 1 {
if c[i] != "+" && c[i] != "-" && c[i] != "*" && c[i] != "/" {
//push number
let number = c[i]
myRPNArray.append(number)
} else {
//if this is the first operand put it on the opStack
if operandArray.count == 0 {
let firstOperand = c[i]
operandArray.append(firstOperand)
} else {
if c[i] == "+" || c[i] == "-" {
operandArray.reverse()
myRPNArray.append(contentsOf: operandArray)
operandArray = []
let uniqOperand = c[i]
operandArray.append(uniqOperand)
} else if c[i] == "*" || c[i] == "/" {
let strongOperand = c[i]
//If I want my mult./div. from right(eg because of parenthesis) the line below is all I need
//--------------------------------
// operandArray.append(strongOperand)
//----------------------------------
//If I want my mult./div. from left
let lastOperand = operandArray[operandArray.count - 1]
if lastOperand == "+" || lastOperand == "-" {
operandArray.append(strongOperand)
} else {
myRPNArray.append(lastOperand)
operandArray.removeLast()
operandArray.append(strongOperand)
}
}
}
}
}
//when I have no more numbers I append the reversed operant array
operandArray.reverse()
myRPNArray.append(contentsOf: operandArray)
operandArray = []
print("RPN: \(myRPNArray)")
return myRPNArray
}
and then we enter the RPN array in the function below to calculate the result. In every loop we remove the numbers and the operand used before and we import the previous result and two "p" in the array so in the end we are left with the solution and an array of "p".
func getResultFromRPNarray(myArray: [String]) -> Double {
var a = [String]()
a = myArray
print("a: \(a)")
var result = Double()
let n = a.count
for i in 0...n - 1 {
if n < 2 {
result = Double(a[0])!
} else {
if a[i] == "p" {
//Do nothing else. Calculations are over and the result is in your hands!!!
} else {
if a[i] == "+" {
result = Double(a[i-2])! + Double(a[i-1])!
a.insert(String(result), at: i-2)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.insert("p", at: 0)
a.insert("p", at: 0)
} else if a[i] == "-" {
result = Double(a[i-2])! - Double(a[i-1])!
a.insert(String(result), at: i-2)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.insert("p", at: 0)
a.insert("p", at: 0)
} else if a[i] == "*" {
result = Double(a[i-2])! * Double(a[i-1])!
a.insert(String(result), at: i-2)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.insert("p", at: 0)
a.insert("p", at: 0)
} else if a[i] == "/" {
result = Double(a[i-2])! / Double(a[i-1])!
a.insert(String(result), at: i-2)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.insert("p", at: 0)
a.insert("p", at: 0)
} else {
// it is a number so do nothing and go the next one
}
}//no over yet
}//n>2
}//iterating
return result
}//Func

It is possible to do "if \(var1) = 0"?

var a = 0
(... up to var z = 0)
let letterchoosedbyplayer:String = LetterChoosed.text!
"LetterChoosed" is a textbox. The player enter a letter in this textbox.
I store the value in the variable "letterchoosedbyplayer".
Then i want to check if the variable called 'letterchoosedbyplayer' (it must be a letter of the alphabet) is equal to 1.
How can i do that?
I want to do that :
if \(letterchoosedbyplayer) = 1 {
}
Last Edit : All my code
let letterchoosedbyplayer:String = LetterChoosed.text!
if Int(letterchoosedbyplayer) == 1 {
print("vous avez perdu")
}
else {
switch letterchoosedbyplayer {
case "a":
print("lettre \(letterchoosedbyplayer) choisie")
a = 1
case "b":
print("lettre \(letterchoosedbyplayer) choisie")
b = 1
default:
print("cas défaut")
}
}
\() is used to append any object in a string. I don't think you can use this for your need
Try
if let letterchoosedbyplayer = LetterChoosed.text where letterchoosedbyplayer == "1" {
}
You could include the "1" case in the switch statement:
let letterchoosedbyplayer = LetterChoosed.text
if let lettrechoisie = letterchoosedbyplayer where !lettrechoisie.isEmpty {
switch lettrechoisie {
case "1": print("vous avez perdu")
case "a":
print("lettre \(lettrechoisie) choisie")
a = 1
case "b":
print("lettre \(lettrechoisie) choisie")
b = 1
default:
print("cas défaut")
}
}
Note that Int(letterchoosedbyplayer)! == 1 and letterchoosedbyplayer == "1" is the same thing.
Edit:
For your purpose you might use a dictionary rather than more than 20 single variables
var letterDict : [String : Int] = ["a" : 0, "b" : 0, "c" : 0, ... "z" : 0]
You can set a variable to 1 for example
letterDict["f"] = 1
Then you can check
if let lettrechoisie = letterchoosedbyplayer where !lettrechoisie.isEmpty {
let value = letterDict[lettrechoisie]!
if value == 1 {
// do something
} else {
// do something else
}
}
That avoids also a huge switch statement.

In Swift, how do I sort an array of strings and have strings of numbers, symbols, etc. always come after alphabetic strings?

I want to sort an array of strings so that alphabetic characters are always before any other kinds of characters. For example:
["800", "word", "test"]
Should sort to:
["test", "word", "800"]
The alphabetic strings can have numbers in them, but they can't have them as the first letter. So for example, if it's "ab8s" that should still come before "dog".
How would I do this? The comparison operators in Swift by default sort numbers before letters.
The key is to write your "is ordered before" function to do whatever you want. For example, if by digits, you mean "0"..."9", then something like this is probably what you want:
func isDigit(c: Character) -> Bool {
return "0" <= c && c <= "9"
}
func sortedLettersFirst(lhs: String, rhs: String) -> Bool {
for (lc, rc) in zip(lhs.characters, rhs.characters) {
if lc == rc { continue }
if isDigit(lc) && !isDigit(rc) {
return false
}
if !isDigit(lc) && isDigit(rc) {
return true
}
return lc < rc
}
return lhs.characters.count < rhs.characters.count
}
words.sort(sortedLettersFirst)
Of course, if by "digit" you mean "unicode digits", then see What is the replacement for isDigit() for characters in Swift? for a different approach to isDigit. But ultimately, the point is to make whatever rule you want in your isOrderedBefore function, and pass that to sort().
How about this.
func sortedNumbersLast(words: [String]) -> [String] {
var startsWithDigit = [String]()
var startsWithCharacter = [String]()
for word in words {
if let first = word.characters.first {
if first >= "0" && first <= "9" {
startsWithDigit.append(word)
}
else {
startsWithCharacter.append(word)
}
}
}
return startsWithCharacter.sort(<) + startsWithDigit.sort(<)
}
Try this in Playground, as you can see in the console output it gets the job done, letters are being placed at the front, followed by numbers and other symbols are at the end.
let stringsSortedByLettersFirstNumbersThenAndOtherSymbolsAtTheEnd: (String, String) -> Bool = { s1, s2 -> Bool in
guard let f1 = s1.first, let f2 = s2.first else {
return s1 < s2
}
if f1.isLetter == false && f2.isLetter {
return false
}
if f1.isLetter && f2.isLetter == false {
return true
}
if f1.isNumber == false && f2.isNumber {
return false
}
if f1.isNumber && f2.isNumber == false {
return true
}
return s1 < s2
}
let str = ["4", "A", "B", "Z", "T", "3", "'", "8"]
print(str.sorted(by: stringsSortedByLettersFirstNumbersThenAndOtherSymbolsAtTheEnd))
Above method sorts String in ascending order, if you want to do the other way just change the lines
return s1 < s2
to
return s1 > s2

Hex String to Character in PURE Swift

I need a way to convert a string that contains a literal string representing a hexadecimal value into a Character corresponding to that particular hexadecimal value.
Ideally, something along these lines:
let hexString: String = "2C"
let char: Character = fromHexString(hexString)
println(char) // prints -> ","
I've tried to use the syntax: "\u{n}" where n is a Int or String and neither worked.
This could be used to loop over an array of hexStrings like so:
var hexArray = ["2F", "24", "40", "2A"]
var charArray = [Character]()
charArray = map(hexArray) { charArray.append(Character($0)) }
charArray.description // prints -> "[/, $, #, *]"
A couple of things about your code:
var charArray = [Character]()
charArray = map(hexArray) { charArray.append(Character($0)) }
You don't need to create an array and then assign the result of the map, you can just assign the result and avoid creating an unnecessary array.
charArray = map(hexArray) { charArray.append(Character($0)) }
Here you can use hexArray.map instead of map(hexArray), also when you use a map function what you are conceptually doing is mapping the elements of the receiver array to a new set of values and the result of the mapping is the new "mapped" array, which means that you don't need to do charArray.append inside the map closure.
Anyway, here is a working example:
let hexArray = ["2F", "24", "40", "2A"]
var charArray = hexArray.map { char -> Character in
let code = Int(strtoul(char, nil, 16))
return Character(UnicodeScalar(code))
}
println(charArray) // -> [/, $, #, *]
EDIT: This is another implementation that doesn't need Foundation:
func hexToScalar(char: String) -> UnicodeScalar {
var total = 0
for scalar in char.uppercaseString.unicodeScalars {
if !(scalar >= "A" && scalar <= "F" || scalar >= "0" && scalar <= "9") {
assertionFailure("Input is wrong")
}
if scalar >= "A" {
total = 16 * total + 10 + scalar.value - 65 /* 'A' */
} else {
total = 16 * total + scalar.value - 48 /* '0' */
}
}
return UnicodeScalar(total)
}
let hexArray = ["2F", "24", "40", "2A"]
var charArray = hexArray.map { Character(hexToScalar($0)) }
println(charArray)
EDIT2 Yet another option:
func hexToScalar(char: String) -> UnicodeScalar {
let map = [ "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
"A": 10, "B": 11, "C": 12, "D": 13, "E": 14, "F": 15 ]
let total = reduce(char.uppercaseString.unicodeScalars, 0, { $0 * 16 + (map[String($1)] ?? 0xff) })
if total > 0xFF {
assertionFailure("Input char was wrong")
}
return UnicodeScalar(total)
}
Final edit: explanation
Given that the ascii table has all the number together (012345679), we can convert 'N' (base 10) to an integer knowing the ascii value of 0.
Because:
'0': 48
'1': 49
...
'9': 57
Then if for example you need to convert '9' to 9 you could do
asciiValue('9') - asciiValue('0') => 57 - 48 = 9
And you can do the same from 'A' to 'F':
'A': 65
'B': 66
...
'F': 70
Now we can do the same as before but, for example for 'F' we'd do:
asciiValue('F') - asciiValue('A') => 70 - 65 = 5
Note that we need to add 10 to this number to get the decimal. Then (going back to the code): If the scalar is between A-Z we need to do:
10 + asciiValue(<letter>) - asciiValue('A')
which is the same as: 10 + scalar.value - 65
And if it's between 0-9:
asciiValue(<letter>) - asciiValue('0')
which is the same as: scalar.value - 48
For example: '2F'
'2' is 2 and 'F' is 15 (by the previous example), right?. Since hex is base 16 we'd need to do:
((16 ^ 1) * 2) + ((16 ^ 0) * 15) = 47
Here you go:
var string = String(UnicodeScalar(Int("2C", radix: 16)!))
BTW, you can include hex values in the literal strings like this:
var string = "\u{2c}"
With Swift 5, you will have to convert your string variable into an integer (using init(_:radix:) initializer), create Unicode scalar from this integer (using init(_:)) then create a character from this Unicode scalar (using init(_:)).
The Swift 5 Playground sample code below shows how to proceed:
let validHexString: String = "2C"
let validUnicodeScalarValue = Int(validHexString, radix: 16)!
let validUnicodeScalar = Unicode.Scalar(validUnicodeScalarValue)!
let character = Character(validUnicodeScalar)
print(character) // prints: ","
If you want to perform this operation for the elements inside an array, you can use the sample code below:
let hexArray = ["2F", "24", "40", "2A"]
let characterArray = hexArray.map({ (hexString) -> Character in
let unicodeScalarValue = Int(hexString, radix: 16)!
let validUnicodeScalar = Unicode.Scalar(unicodeScalarValue)!
return Character(validUnicodeScalar)
})
print(characterArray) // prints: ["/", "$", "#", "*"]
Alternative with no force unwraps:
let hexArray = ["2F", "24", "40", "2A"]
let characterArray = hexArray.compactMap({ (hexString) -> Character? in
guard let unicodeScalarValue = Int(hexString, radix: 16),
let unicodeScalar = Unicode.Scalar(unicodeScalarValue) else {
return nil
}
return Character(unicodeScalar)
})
print(characterArray) // prints: ["/", "$", "#", "*"]
Another simple way based on ICU transforms:
extension String {
func transformingFromHex() -> String? {
return "&#x\(self);".applyingTransform(.toXMLHex, reverse: true)
}
}
Usage:
"2C".transformingFromHex()
Results in: ,

Character Arithmetic in Swift

Consider the following code snippet to convert a hex Character to an integer value
extension Character {
var hexValue : UInt {
let zero : Character = "0"
let nine : Character = "9"
let a : Character = "a"
let f : Character = "f"
let A : Character = "A"
let F : Character = "F"
if self >= zero && self <= nine {
return self - zero
}
if self >= a && self <= f {
return self - a + 10
}
if self >= A && self <= F {
return self - A + 10
}
return 0
}
}
Unfortunately the Swift compiler doesn't like the +/- operations on Character.
How can I do arithmetic operations on Characters in Swift?
I found the answer when I dug around the Swift headers. We can use UnicodeScalar for this, like so:
UnicodeScalar("a").value
value will give you the character integer value
To convert an arbitrary Character you can do this
let s = String(myChar).unicodeScalars
let i = scalars[s.startIndex].value
Try NSScanner:
var hexChar = "A"
var hexValue:UInt32 = 0
let scanner = NSScanner(string: hexChar)
scanner.scanHexInt(&hexValue)
println(hexValue) // prints 10