Xcode 如何在Swift中实现ROT13功能?

Xcode 如何在Swift中实现ROT13功能?,xcode,string,swift,rot13,Xcode,String,Swift,Rot13,我想创建一个函数,它接收一个字符串并返回一个字符串,然后用字母表中的13个字母替换一个字母(ROT13)。我发现了很多例子,不幸的是,由于各种各样的错误,我没能让它工作。例如,这个: var key = [String:String]() // EDITED let uppercase = Array(arrayLiteral: "ABCDEFGHIJKLMNOPQRSTUVWXYZ") let lowercase = Array(arrayLiteral: "abcdefghijklmnopq

我想创建一个函数,它接收一个字符串并返回一个字符串,然后用字母表中的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 }))
}
var key=[String:String]()//已编辑
让大写=数组(数组并行:“ABCDEFGHIJKLMNOPQRSTUVWXYZ”)
let lowercase=Array(arrayLiteral:“abcdefghijklmnopqrstuvwxyz”)
对于0..<26中的i{
键[大写[i]]=大写[(i+13)%26]
键[小写[i]]=小写[(i+13)%26]
}
func rot13(s:String)->String{
返回字符串(映射,{key[$0]?$0}))
}

实际上,您最初映射
字符的方法很好:

var key = [Character: Character]()
但是这两个数组必须是
字符的数组

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]
}

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

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)

这是@AMomchilov的
rot13
的另一个版本,它使用
开关
和较少的数学运算,并消除了幻数:

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
函数,并通过让它们采用
ClosedRange
数组,将它们推广到
rotN
。这允许您以非常简单的方式实现
rot13
rot47
rot5
,以及
rot13
rot5
的组合

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

    for interval in intervals {
        let half = (interval.upperBound.value - interval.lowerBound.value + 1) / 2
        let halfway = UnicodeScalar(interval.lowerBound.value + half)!

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

    return Character(UnicodeScalar(result)!)
}

func rotN(_ input: String, intervals:[ClosedRange<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"

为什么不将键数组设置为字符串数组?您正在尝试使用
$0
中获取一个元素,它是
字符
,而不是
整数
,谢谢。我现在将键设置为字符串数组。现在字符串seq有一个问题:“无关参数标签'seq:'in call”我已经扩展了我的答案,将其推广到
rotN
,这使得
rot13
rot47
rot5
,以及
rot13
的组合的实现变得简单。您的Swift 3正在显示。对于Swift 2.2的兼容性,您可能需要注意
resultUSV.appendContentsOf(resultUSs)
。啊,是的,我是在IBM的Swift沙盒中写的,它只有Swift 3。是的,我希望他们能让您选择Swift 2.2和Swift 3。在Xcode 8成为GM之前,这将是一段过渡时间。最后一件事:您需要一个大写的
U
,用于
返回UnicodeScalar(结果)
。谢谢;)现在修复了这是一个有趣的方法。我喜欢范围检查开关。我忘了那是可能的;太有用了!不过,我不喜欢删除mod 13的解决方案,因为这使得很难将其推广到rotN。我认为更好的解决办法是将我的两行数学公式分解成一个单独的参数化函数。@AMomchilov,我接受了你的挑战,并推广到
rotN
:-)。不错,但我仍然希望避免
%
增加不必要的内容complexity@AMomchilov,我在原始代码的基础上添加了一个基于
%
的版本。我把它改为return
Character
,使调用代码更简单。我喜欢它!好了!
func rotN(_ unicodeScalar: UnicodeScalar, intervals:[ClosedRange<UnicodeScalar>]) -> Character {
    var result = unicodeScalar.value

    for interval in intervals {
        let half = (interval.upperBound.value - interval.lowerBound.value + 1) / 2
        let halfway = UnicodeScalar(interval.lowerBound.value + half)!

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

    return Character(UnicodeScalar(result)!)
}

func rotN(_ input: String, intervals:[ClosedRange<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"
func rotN(_ unicodeScalar: UnicodeScalar, intervals:[ClosedRange<UnicodeScalar>]) -> UnicodeScalar {
    var result = unicodeScalar.value
    
    for interval in intervals {
        let start = interval.lowerBound.value
        let length = interval.upperBound.value - start + 1
        
        if interval ~= unicodeScalar {
            result = (result + length/2 - start) % length + start
        }
    }
    
    return UnicodeScalar(result)!
}

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