멀고도 험난한 개발 일지

[Swift 알고리즘] split() vs components()

이드entity 2023. 3. 14. 02:03
반응형

새로운 분류의 글을 올리기 시작!!

바로 알고리즘!

취준을 위해 천천히 조금씩 진행하려 한다 ㅎㅎ

 

예전에 파이썬으로 조금 풀다가 그만했었는데 다시 swift로 시작!

백준 브론즈부터 풀고 있는데 참 짜증나는 점을 알게 됐다 ^____^

 

[오늘의 문제]

 

10818번: 최소, 최대

첫째 줄에 정수의 개수 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 N개의 정수를 공백으로 구분해서 주어진다. 모든 정수는 -1,000,000보다 크거나 같고, 1,000,000보다 작거나 같은 정수이다.

www.acmicpc.net

브론즈 3 문제다

근데 처참함...

ㅋㅋㅋㅋㅋㅋㅋㅋㅋ

아니 브론즈3인데 이게 뭐냐고 ㅋㅋㅋㅋㅋㅋㅋㅋ

 

 

1트

import Foundation

var cnt = Int(readLine()!)!
var nums: [Int] = readLine()!.components(separatedBy: " ").map { Int($0)! }
var maxN = nums[0]
var minN = nums[0]
for i in 1..<cnt {
    maxN = max(maxN, nums[i])
    minN = min(minN, nums[i])
}
print("\(minN) \(maxN)")

 

 

2트

import Foundation

var cnt = Int(readLine()!)!
var nums: [Int] = readLine()!.components(separatedBy: " ").map { Int($0)! }
var sortedNums = nums.sorted()
print("\(sortedNums[0]) \(sortedNums[cnt-1])")

 

 

3트

import Foundation

var cnt = Int(readLine()!)!
var nums: [Int] = readLine()!.components(separatedBy: " ").map { Int($0)! }.sorted()
print("\(nums.first!) \(nums.last!)")

 

 

 

이렇게까지 해봤는데 정말 모르겠어서 구글링 해보니

components()에 문제가 있었다...

 

그래서 나온 정답

import Foundation // 사실 얘도 없어도 됨

var cnt = Int(readLine()!)!
var nums: [Int] = readLine()!.split(separator: " ").map { Int($0)! }
print("\(nums.min()!) \(nums.max()!)")

 


 

왜 split()은 되고 components()는 안되는건데!!!! 에서 둘의 차이에 궁금증이 생겼다

그래서 또 구글링 해보니까 꽤나 명확했다

 

일단 components()의 공식문서

 

먼저 components()는 Foundation 을 import 해주어야 함

 

공식문서 보면 입력값이 하나다

seperatedBy: String

 

·

 

seperatedBy의 String 값으로 어떤 문자열을 기준으로 seperate 할 지 정해줌

(항상 느끼는건데 swift는 가독성이 참 좋아~)

 

·

 

그리고 반환값은 [String]

 

그래서 알고리즘같은거 풀 때

import Foundation

var nums = readLine()!.components(seperatedBy: " ").map { Int($0)! }

요롷게 " " 을 입력값으로 넣어 공백으로 나뉘어진 문자열을 split 해준다

( 뒤에 map 함수 사용해서 string 으로 되어 있는 반환값을 Int로 변환함 )

 

·

·

·

 

그리고 split()의 공식문서

 

얘는 기본적으로 swift에 딸려있는 애라 따로 import 해줄거는 없음

 

그리고 입력값이 무려 3개! (필수로 필요한 애는 seperator이다)

seperator: Self.Element

maxSplits: Int

omittingEmptySubsequences: Bool

 

얘도 components와 비슷하게 seperator의 값으로 어떤걸 기준으로 분류해줄지 결정한다

하지만 components와는 다르게 타입이 Self.Elements인데

split()이 어떤 array에 사용되잖슴?

그 array의 element의 타입을 말한다고 함!!

고로 [String] 타입이라면 Self.Elements는 String 타입일거고,

[Int] 타입이라면 Self.Elements는 Int 타입이겠지

 

·

 

그 다음 입력값인 maxSplits 는 최대 몇 개로 쪼갤지를 입력값으로 받는다

공식 문서에 maxSplits: Int = Int.max 로 되어 있는데,

Default 값이 Int.max라는 의미이고, 이는 Int 형에서 가장 큰 수라고 보면 될 것 같다!

즉, 입력값을 넣지 않으면 가능한 만큼 쪼개는 듯?

 

·

 

그 다음은 omittingEmptySubsequences 인데,

이건 omitting(생략하다)Empty(비어있는)Subsequence(부분문자열)

즉, 쪼갠 결과물들 중에 빈 문자열을 포함할까 말까? 라는 것이다

 

만약 "1 2 3   4 5"를 입력값으로 한다면 (띄어쓰기 3번 함)

true 일 때에는, ["1", "2", "3", "4", "5"]

false 일 때에는, ["1", "2", "3", "", "", "4", "5"] (띄어쓰기 3개 사이에 2개의 ""이 포함되기 때문)

이런 반환값이 나온다

 

기본값은 true라고 한다!

 

·

 

그리고 반환값은 [Self.Subsequence] 

본인 array의 Element로 이루어진 배열이라고 생각하면 될 듯!

(Subsequence의 정확한 의미 아시는 분 댓글 달아주세요...)

 


 

결국 여기서 왜 components()로는 안됐던게 split()으로는 됐냐!라고 한다면

이유는 omittingEmptySubsequences 와 때문이라고 생각한다!

 

components()와 split()을 사용했을 때의 예시의 결과는 다음과 같다

import Foundation

var nums = "1 2 3   4 5"
print(nums.components(separatedBy: " ")) // ["1", "2", "3", "", "", "5"]
print(nums.split(separator: " ")) // ["1", "2", "3", "4", "5"]

components()는 "" 라는 애도 만들어 두기 때문에 .map() 함수로 Int 형으로 강제언래핑 한다면 컴파일 에러가 뜨는 것!

 

다만 여기서 좀 이상한 점이 발생하는데,,,,

import Foundation

var nums = "1 2 3   4 5"
print(nums.components(separatedBy: " ").map { Int($0)! }) // 컴파일 에러

이렇게 실행시키면 위에 써 둔 것처럼 컴파일에러가 뜬다 

 

에러 자체가 이상하다는게 아니라,

components()를 사용해서 10818: 최소, 최대 문제를 풀면

'틀렸습니다'나 '컴파일에러'가 뜨는게 아니라 '시간 초과'가 뜨는것

흠 원래 백준에선 컴파일 에러를 시간초과로 처리하나...

 

구글링 해보니까 시간복잡도에서 차이가 나는 것도 아닌 것 같은데 왜일까....

 

 

[수정]

조금 더 생각해보니까 왜 '시간초과가 떴는지 알 것 같기도 해서 작성한다

components()는 비어 있는 문자도 분리 해주는데,

백준에서 입력값을 "1                                                      2" (띄어쓰기 엄청 많이)

이런 식으로 해서 분리하는데에 시간이 오래 걸린 것 같기도..??

 

 

무튼 이렇게 해서 components()split()의 차이 구분 완료!

 


 

[출처]

 

Swift의 문자열 처리 (split vs components)

안녕하세요. 그린입니다🍏 이번 포스팅에서는 Swift에서의 문자열 처리를 해주는 두 메서드 split과 components에 대해 학습해보겠습니다🙌 Swift 언어의 특성상 문자열을 타 언어보다 다루기가 조금

green1229.tistory.com

반응형