如何在Swift中实现ROT13功能?

时间:2016-06-10 20:10:33

标签: xcode string swift rot13

我想创建一个接收String并返回String的函数,并在字母表中用字母后面的字母替换13个字母(ROT13)。我发现了很多例子,遗憾的是由于各种错误,我无法让它工作。例如这一个:

var key = [String:String]() // EDITED
let uppercase = Array(arrayLiteral: "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
let lowercase = Array(arrayLiteral: "abcdefghijklmnopqrstuvwxyz")
for i in 0 ..< 26 {
    key[uppercase[i]] = uppercase[(i + 13) % 26]
    key[lowercase[i]] = lowercase[(i + 13) % 26]
}

func rot13(s: String) -> String {
    return String(map(s, { key[$0] ?? $0 }))
}

3 个答案:

答案 0 :(得分:5)

实际上,最初的Character映射方法很好:

var key = [Character: Character]()

但是这两个数组必须是Characters的数组:

let uppercase = Array("ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters)
let lowercase = Array("abcdefghijklmnopqrstuvwxyz".characters)

备注:您(几乎)永远不想调用xxxLiteral:初始值设定项 明确。这样做(几乎)总是隐藏实际问题。)

现在填写字典的代码有效:

for i in 0 ..< 26 {
    key[uppercase[i]] = uppercase[(i + 13) % 26]
    key[lowercase[i]] = lowercase[(i + 13) % 26]
}

转换字符串可以作为

完成
//                       map
// String --> Characters ---> Characters -> String

func rot13(s: String) -> String {
    return String(s.characters.map { key[$0] ?? $0 })
}

答案 1 :(得分:5)

这是另一种不使用查找数组的方法:

let input = "Hello World"

func rot13(unicodeScalar: UnicodeScalar) -> UnicodeScalar {
    var result = unicodeScalar.value

    if 65...90 ~= result { //Detect capital A ... Z
        result = (result + 13 - 65) % 26 + 65
    }
    else if 97 ... 122 ~= result { //Detect lowercase a ... z
        result = (result + 13 - 97) % 26 + 97
    }

    return UnicodeScalar(result)
}

func rot13(_ input: String) -> String {
    let resultUSs = input.unicodeScalars.map(rot13)

    var resultUSV = String.UnicodeScalarView()
    resultUSV.appendContentsOf(resultUSs) //for Swift 2.2
    //resultUSV.append(contentsOf: resultUSs) //for Swift 3.0
    return String(resultUSV)
}

let output = rot13(input)

print(output)

答案 2 :(得分:3)

这是@ AMomchilov的rot13的替代版本,它使用switch而不是数学并消除幻数:

func rot13(unicodeScalar: UnicodeScalar) -> Character {
    var result = unicodeScalar.value

    switch unicodeScalar {
    case "A"..."M", "a"..."m":
        result += 13
    case "N"..."Z", "n"..."z":
        result -= 13
    default:
        break
    }

    return Character(UnicodeScalar(result))
}

func rot13(input: String) -> String {
    return String(input.unicodeScalars.map(rot13))
}

print(rot13("Uryyb, jbeyq!")) // "Hello, world!"

泛化为rotN

我已采用上面的rot13函数,并通过让他们采用rotN数组将它们推广到ClosedInterval<UnicodeScalar>。这样,您就可以非常直接的方式实施rot13rot47rot5以及rot13rot5的组合。

func rotN(unicodeScalar: UnicodeScalar, intervals:[ClosedInterval<UnicodeScalar>]) -> Character {
    var result = unicodeScalar.value

    for interval in intervals {
        let half = (interval.end.value - interval.start.value + 1) / 2
        let halfway = UnicodeScalar(interval.start.value + half)

        switch unicodeScalar {
        case interval.start..<halfway:
            result += half
        case halfway...interval.end:
            result -= half
        default:
            break
        }
    }

    return Character(UnicodeScalar(result))
}

func rotN(input: String, intervals:[ClosedInterval<UnicodeScalar>]) -> String {
    return String(input.unicodeScalars.map {rotN($0, intervals: intervals)})
}

func rot13(input: String) -> String {
    return rotN(input, intervals:["A"..."Z", "a"..."z"])
}

func rot47(input: String) -> String {
    return rotN(input, intervals:["!"..."~"])
}

func rot5(input: String) -> String {
    return rotN(input, intervals:["0"..."9"])
}

func rot13and5(input: String) -> String {
    return rotN(input, intervals:["A"..."Z", "a"..."z", "0"..."9"])
}

print(rot13("Uryyb, jbeyq!"))        // "Hello, world!"
print(rot47("%96 BF:4< 3C@H? 7@I"))  // "The quick brown fox"
print(rot5("6 + 7 = 8"))             // "1 + 2 = 3"
print(rot13and5("Whyl 9, 6221"))     // "July 4, 1776"

以下是基于rotN原始@AMomchilov's的{​​{1}}版本:

rot13