문제 설명 어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 됩니다. 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요. 제한 조건 공백은 아무리 밀어도 공백입니다.s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다.s의 길이는 8000이하입니다.n은 1 이상, 25이하인 자연수입니다.
입출력 예
🔵 풀이 - UnicodeScalar 사용
for...in 문으로 String을 Character로 하나하나씩 분리한 후,
소문자면 소문자 어레이에서, 대문자면 대문자 어레이에서, 공백이면 공백 그대로 밀면 된다.
이를 이용해서, A~Z, a~z를 각각 upperCase 와 lowerCase 배열에 담을 계획이다!
* 유니코드 함수를 이용하지 않고 배열에 따로 담는 이유: UnicodeScalar는 BidirectionalCollection이라서 함수의 시간복잡도가 O(N)으로 높다. for...in 루프에서 계속 UnicodeScala를 사용하면 코드가 무거워 질 것이라 생각한다.
▶️ 코드 작성
🔽 알파벳 어레이 만들기
🔽 for 문으로 문자 확인 및 밀기
character의 인덱스에 n을 더했을 때 array의 범위를 넘어가게 될 수 있으므로,
(인덱스 + n) 을 26으로 나눈 나머지를 구했다.
** 알파벳 array는 0부터 25번 인덱스까지 있다.
전체 코드는 다음과 같다.
func solution(_ s:String, _ n:Int) -> String {
var upperCase: [Character] = []
var lowerCase: [Character] = []
var newString: String = ""
// upperCase loop
for i in 65...90 {
upperCase.append(Character(UnicodeScalar(i)!))
}
// lowerCase loop
for i in 97...122 {
lowerCase.append(Character(UnicodeScalar(i)!))
}
// 문자 확인 및 밀기
for character in s {
if character.isUppercase { // 대문자인 경우
let pushedIndex = (upperCase.firstIndex(of: character)! + n) % 26
newString += String(upperCase[pushedIndex])
} else if character.isLowercase { // 소문자인 경우
let pushedIndex = (lowerCase.firstIndex(of: character)! + n) % 26
newString += String(lowerCase[pushedIndex])
} else if character == " " { // 공백인 경우
newString += " "
}
}
return newString
}