이번 문제는 별 그리기 같은 문제입니다.
해당 문제에서 한 가지 오류가 있는데 메서드 리턴값이 옵셔널이 아닙니다. 반면 테스트 케이스는 옵셔널을 가정하고 있습니다.
따라서 func diamond(_ size: Int) -> String? { 과 같이 변경해주셔야 합니다.
일단 문제 자체는 크게 어렵지 않으니 방법만 간단히 보겠습니다.
1. Swift
1-1. 본인의 풀이
func diamond(_ size: Int) -> String? {
if size != abs(size) {
return nil
}
guard size % 2 == 1 else {
return nil
}
let val : Int = (size - 1) / 2
var totalStr : String = ""
for i in 0 ..< size {
var tempStar: String = ""
let spacebar = abs(val - i)
for _ in 0 ..< spacebar {
tempStar += " "
}
for _ in 0 ..< size - (spacebar * 2) {
tempStar += "*"
}
totalStr += tempStar + "\n"
}
return totalStr
}
저는 최대한 단순하게 생각하기 위해서 모두 풀어서 썼습니다. 다만 for문 안에 또 for문이 반복되기 때문에 시간복잡도로는 좋지 않다고 할 수 있겠네요.
먼저 size값이 음수 또는 홀수가 아닌 수일 때는 return nil을 해줍니다.
그 후 size만큼 for문을 돌리게 됩니다. 그 이유는 형태를 보면 금방 이해하실 수 있으신데, size가 3인 경우 3줄, 5일 경우 5줄 이런 식으로 규칙이 존재하기 때문입니다.
그 다음 *을 그리기 전 space bar 갯수를 계산하여 앞에 추가하고 그 후에 *을 특정 갯수만큼 그려줍니다.
1-2. Best Solution
hmccabe유저의 답이 가장 많은 Best Practice와 Clever를 받았습니다.
func diamond(_ size: Int) -> String? {
guard size > 0 && size % 2 == 1 else {
return nil
}
var diamond = ""
let centerRow = size/2 + 1
for row in 1...size {
let spaces = abs(centerRow - row)
diamond += String(repeating: " ", count: spaces) + String(repeating: "*", count: size-spaces*2) + "\n"
}
return diamond
}
코드를 보면 일단 guard문은 제가 풀어 쓴 if문을 한 번에 처리한 것입니다.
centerRow의 경우는 swift int의 특징을 이용한 것이라고 보시면 되겠는데, 예를 들어 size가 5인 경우 2로 나누면 값이 2가 나오기 때문에 위의 코드처럼 사용한 것입니다.
for문은 5만큼 돌게 될 것이고, spaces는 각 row와 centerRow의 차이의 절대값을 이용한 것입니다.
그 다음 줄에서 제가 생각을 안 하고 있던 부분이었는데, 위의 유저의 경우 String(repeating:, count:) 를 사용했습니다.
실무에서 저는 거의 쓴 적이 없는 방식이다보니 생각을 못 했네요.
이번 문제는 각 값의 규칙성을 찾아내면 그나마 쉽게 풀 수 있는 문제였습니다.
'Codewars(알고리즘) > 6Kyu' 카테고리의 다른 글
[Codewars] [6Kyu] Parabolic Arc Length (0) | 2022.01.27 |
---|---|
[Codewars] [6Kyu] Persistent Bugger. (0) | 2022.01.26 |
[Codewars] [6Kyu] Moduli number system (0) | 2022.01.26 |
[Codewars] [6Kyu] Consecutive Strings (0) | 2021.03.05 |
[Codewars] [6Kyu] How Much? (0) | 2021.03.05 |