처음 접근 방법을 떠올리는 것이 너무 어려웠다.
주어진 숫자 % 10 으로 정렬하여 풀어보았지만, 주어지는 숫자는 1000 이하의 범위이므로 세자리 숫자일 경우 기존 풀이 방법은 전혀 효과를 보지 못했다.
초기 코드
// 테스트 케이스 2개는 통과했으나 채점 진행 시 대다수 실패
func solution(_ numbers: [Int]) -> String {
return numbers.sorted(by: { $0 % 10 > $1 % 10 })
.map(String.init).joined()
}
매우 헤매던 그때 튜터님의 힌트로 최종 답안을 작성했다.
최종 코드
func solution(_ numbers: [Int]) -> String {
// [6, 10, 2]일 때, "610" > "106" 중 큰 수를 비교해 큰 것대로 나열
let result = numbers.sorted(by: {
($0.description + $1.description) > ($1.description + $0.description)
}).map(String.init).joined()
// 주어진 numbers가 [0, 0, 0, 0]이라면 결과가 "0000" -> "0"으로 변환
return Int(result) == 0 ? "0" : result
}
결과는 얻었는데 sorted가 어떻게 동작하는지를 잘 모르겠었다..
평소에도 sorted 메서드를 감으로만 사용했던 느낌이 있어 하나씩 써보며 이해해보았다.
단순한 .sorted() 메서드로 사용했을 때라면 아래와 같을 것이다.
[1, 5, 680, 390, 248].sorted()
// 1 > 5 ? [1, 5] : [5, 1] -> [5, 1] => [5, 1, 680, 390, 248]
// 1 > 680 ? [1, 680] : [680, 1] -> [680, 1] => [5, 680, 1, 390, 248]
// 1 > 390 ? [1, 390] : [390, 1] -> [390, 1] => [5, 680, 390, 1, 248]
// 1 > 248 ? [1, 248] : [248, 1] -> [248, 1] => [5, 680, 390, 248, 1]
// 5 > 680 ? [5, 680] : [680, 5] -> [680, 5, 390, 248, 1]
...
// 결과: [680, 390, 248, 5, 1]
다음은 클로저를 통해 조건을 주었을 때이다. 위 답안 코드를 조건으로 사용한다.
[6, 10, 2].sorted(by: closure)
// "610" > "106" ? [6, 10] : [10, 6] -> [6, 10, 2]
// "102" > "210" ? [10, 2] : [2, 10] -> [6, 2, 10]
// "62" > "26" ? [6, 2] : [2, 6] -> [6, 2, 10]
[3, 30, 34, 5, 9].sorted(by: closure)
// "330" > "303" -> [3, 30, 34, 5, 9]
// "3034" > "3430" -> [3, 34, 30, 5, 9]
// "305" > "530" -> [3, 34, 5, 30, 9]
// "309" > "930" -> [3, 34, 5, 9, 30]
// "334" > "343" -> [34, 3, 5, 9, 30]
// "35" > "53" -> [34, 5, 3, 9, 30]
// "39" > "93" -> [34, 5, 9, 3, 30]
// "330" > "303" -> [34, 5, 9, 3, 30]
// "345" > "534" -> [5, 34, 9, 3, 30]
// "349" > "934" -> [5, 9, 34, 3, 30]
// "343" > "334" -> [5, 9, 34, 3, 30]
// "59" > "95" -> [9, 5, 34, 3, 30]
// "534" > "345" -> [9, 5, 34, 3, 30]
sorted(by:)의 조건으로 사용되는 클로저는 bool값을 반환한다. 결과가 true라면 현재 순서를 유지하고, false라면 $0과 $1의 순서를 바꾼다.
모든 정렬이 완료되었다면 계속 true를 반환할 것이므로 정렬이 종료된다.