프로그래머스 코딩테스트 [ 숫자 문자열과 영단어 ]
Github 링크
- 이 문제를 처음 Python으로 풀었을때는 당연히 str의 Index하나하나 확인하면서 숫자면 숫자로 변경, z면 zero, t면 two,three,ten 이런식으로 했는데, 너무 말도 안되게 비효율적인거 같아서 다른 방법을 고민하려고 헀으나, 그나마 나은게 Index 하나하나 확인하는것이 아니라, 배열에서 해당 숫자 String의 길이만큼 비교하는것이었다.
- 처음 맞닥드린 문제는 index out of bound 로 인한 segementation fault 였다. 나는 단순하게 생각해서 총 두개의 index 값을 생성하고, 하나는 currentIndex, 다른 하나는 currentIndex+숫자String의길이 라고 생각을 했으나, 이건 이상하게 계속 에러가 떴다. 아래 코드를 보면 위에 3줄까지는 무난하게 이해를 할 수 있다. 이제 문제는 if let endIndex = endIndex ? 이게 도대체 무슨뜻일까 한번 찾아봤다.
var currentIndex = s.index(s.startIndex, offsetBy:index)
for i in 0...9 {
let endIndex = s.index(s.startIndex, offsetBy: index + arr[i].count, limitedBy: s.endIndex)
if let endIndex = endIndex, s[currentIndex..<endIndex] == arr[i] {
- 우선 Swift에서 Optional (옵셔널)에 대해서 좀 알아야 한다. 일반 자료형 Int, String 등등은 선언을 하고 초기화를 안해주면 아무것도 할당되지 않지만, 옵셔널 타입으로 자료형을 선언하면 자동으로 nil로 초기화됩니다.
var a : Int // 초기화 안됐고, 아무것도 없음
var b : Int? // nil 로 초기화가 됨
print(a) // 오류
print(b) // nil 출력
- 어떤 차이인지 대충 알았는데, 그러면 왜 optional이 도입이 된걸까? 이를 사용하는 목적은 무엇일까?
- 다른 프로그램에서는 값이 있는지 없는지 확인하기가 쉽지가 않다. 현재 swift에서도 단순 자료형 (var a :Int) 하고 출력을 해봐도 오류가 뜨는것을 알 수 있다. 만약 개발자로서 해당 변수가 값이 없을수도 있는 상황을 표현해야 한다면 Optional이 좋은 선택지가 아니 꼭 필요한 선택지이다.
- Optional binding, Optioanl Chaining, 등등의 방법으로 안전하게 값을 추출할 수 있다. 안전하게? 즉 해당 변수가 초기화가 되어 있지 않는 상태일때도, 안전하게 추출할 수 있다는걸 의미한다.
- 그럼 다시 원래 코드로 돌아가서 if let endIndex = endIndex 는 optional binding의 한 종류다, if let, guard let 구문은 둘다 optioanl binding이다.
if let 상수명 = 옵셔녈변수 {
}else{
}
guard let 상수명 = 옵셔널변수 else {
}
- 두개 의 차이는 if let 구문은 우리가 흔히 보는 조건문이랑 똑같다, if 조건 else 조건 x. guard let 구문은 else만 쓰는 역할을 한다, 즉 꼭 강제로 종료(?), 예외처리를 해야하는 경우만 사용된다.
- 그러면 if let endIndex = endIndex 는 결국 무엇을 의미하느냐, endIndex라는 상수에다가 옵셔널변수 endIndex를 안전하게 할당하고, 옵셔널변수가 nil이 아닌 경우에만 if 안에 코드들이 실행된다.
- 여기까지 이해하고 다시 코드를 봤는데, 어? 그러면 String.Index 타입들은 다 옵셔널인가? 어? CurrentIndex는 왜 그러면 optioanl binding을 사용하지 않는거지????
- 찾아보니 endIndex에서는 내가 오류를 안내기 위해서 limitedBy 매개변수를 사용했다. limitBy 매개변수는 인덱스의 최대 이동을 제한하는것인데, 만약 제시한 limitBy보다 벗어난다면 nil을 반환한다. nil로 반환할수도 있다는것은? Optional 이라는 뜻이다.
- 결국 이렇게 다 풀고 다른사람의 풀이를 봤는데 충격을 받았다.
import Foundation
func solution(_ s:String) -> Int {
let arr = ["zero","one","two","three","four","five","six","seven","eight","nine"]
var str = s
for i in 0..<arr.count {
str = str.replacingOccurrences(of: arr[i], with: String(i))
}
return Int(str)!
}
- 단 몇줄만에 끝난것이다. str.replaceingOccurrences 메서드를 난 몰랐다.이 메서드는 이름만 봐도 알 수 있듯이, String에서 나오는 모든 특정 StringA를 StringB로 변경하는것이다. 심지어 없으면 자동으로 넘어가기 까지한다. 역시 개발을 잘하는건 얼마나 많이 알고 많이 활용하느것의 차이인것 같다.
str = str.replacingOccurrences(of:target, with: dest)
프로그래머스 코딩테스트 [ K번째수 ]
github 링크
- 이문제는 단순히 Array 자르고 정렬인데 새로운 개념 때문에 오류를 찾는데 조금 오래 걸렸다.
- ArraySlice : Array를 자를때 반환되는 타입
var newArr = arr[0...1]
var tempArr = newArr.sorted()
- 단순한건데 ArraySlice로는 접근하는것 자체가 안되기 때문에, 참조용이기 때문에 계속 오류가 났던것이다. 그래서 습관적으로 배열을 자를때는 아래와 같이 하느게 좋을꺼 같다.
var newArr = Array(arr[0...1])
프로그래머스 코딩테스트 [ 가장 가까운 같은 글자 ]
Github 링크
- 이 문제는 처음으로 Dictionary를 썼던 문제 인것 같다.
- 문자열이 주어졌을때 각 위치마다 자신보다 앞에 나왔고, 자신과 가장 가까운곳에 있는 글자를 찾는것인데, Dictionary에 Key는 나타난 String을 부여하고, Value은 index를 만들어 준다.
var dic = Dictionary <String,Int>()
Dictionary.updateValue("바꿀 Value", forKey: 키 값)
- 위코드는 value를 업데이트 하는 메서드인데, 만약 해당 키가 없다면 nil을 반환하고, 있다면 변경된 Value를 반환한다.