dropFirst(), zip(), map(), prefix()

Choong Won, Seo·2024년 4월 26일
0

백준

목록 보기
29/30
post-thumbnail

2212 센서

2212번: 센서

풀이는 간단한다.

입력을 받고, 입력받은 센서를 오름차순(거리순)으로 정렬한다.

각 센서들간의 거리의 차이를 담은 배열을 만들고, 오름차순으로 정렬한 다음, 처음부터, N-K번 index 전까지의 합을 출력하면 된다. (집중국의 수가 K개이므로, 가장 긴 거리의 차이 K-1개를 뺄 수 있다. → (N-1) - (K-1) = N-K)

또, 예외처리를 할게 있는데, 집중국의 수가 센서의 수보다 많은 경우, 모든 센서를 모든 집중국이 담당하면 되므로, 0을 출력한다.

문제에서 어려운 점은 없었는데, 최적화를 진행하는 과정에서 새롭게 배운 내용들이 있었다.

항상 문제를 풀고나면, 시간을 조금 줄일 수 없을까, 아니면 더 간결한 코드를 쓸 수 있지 않을까 하고 GPT나 블로그 풀이 등을 참고하여 최적화를 진행한다.

그 과정에서 조금 새롭게 배운 내용들이 있어서 포스팅하기로 했다.

원래 처음 제출했던 코드는 이 상태였다.

let N = Int(readLine()!)!
let K = Int(readLine()!)!
var arr = readLine()!.split(separator: " ").map{Int(String($0))!}
//거리의 차를 담아줄 배열 생성
var distance = [Int]()
//for문으로 index탐색
for i in 0..<N-1 {
    distance.append(arr[i+1] - arr[i])
}
distance.sort(by: <)

if N < K {
    print(0)
} else {
		//0부터 N-K전까지 더해서 답 제출
    print((0..<N-K).map{distance[$0]}.reduce(0,+))
}

그리고, GPT를 통해 첨삭받은 최적화 코드

let N = Int(readLine()!)!
let K = Int(readLine()!)!
var arr = readLine()!.split(separator: " ").map{Int(String($0))!}
arr.sort(by: <)
var distance = zip(arr.dropFirst(), arr).map(-)
distance.sort(by: <)

print(N < K ? 0 : distance.prefix(N-K).reduce(0, +))
  1. dropFirst()

먼저 dropFirst()이다. 항상 BFS,DFS를 할 때, removeFirst()를 통해서 node를 가져오는 작업은 많이 했었는데, dropFirst()는 생소해서 차이점을 알아보기로 했다.

일단 알고있듯이 removeFirst()같은 경우,

  • mutating function으로, 상수(let)배열에서는 사용하지 못한다.
  • ‘삭제한’ 배열을 return한다.

이와 달리, dropFirst()

  • 삭제할 배열을 제외한 새로운 배열을 방출하는 함수이므로, 상수(let)배열에서도 사용 가능하다.
  • ‘삭제한’ 배열을 제외한 Self.Subsequence를 return한다.
func dropFirst(_ k: Int = 1) -> Self.SubSequence

또한, removeFirst()와 dropFirst()의 파라미터에 인자를 넣을 생각을 못해봤는데, (함수 이름이 first니까 하나만 자르는줄 알았지..) 인자를 넣으면 앞의 2,3,4.. 개의 배열을 한 번에 제거하는 것도 가능하다고 한다.

여기서 그런데 또 새로운 점을 발견했는데.. (끝이없네)

dropFirst()같은 경우 디폴드 값도 있고, 항상 Self.SubSequence를 반환하지만,

removeFirst() 같은 경우, 디폴트 값이 없고, 인자를 넣었을 때와 넣지 않았을 때 함수 자체가 달라져버린다.

1. mutating func removeFirst() -> Element
2. mutating func removeFirst(_ k: Int)

흔히 쓰는 것처럼 인자를 넣지 않았을 때에는 Element(컬렉션의 각 항목)을 return 하는데,

인자를 넣는 순간 반환값이 없어져서 반환값을 받으려면 아래처럼 Void 타입을 명시해주어야 한다.

(사실 그냥 return값 안받고 호출만 하는 것이 적절힌데, ()자료형을 처음 봐서 적어보고 싶었다.)

let element: () = arr.removeFirst(2)

사실 인자를 넣으면 배열 등 컬렉션 형식이 return될 줄 알았는데 의외였다.

  1. zip()

보기는 많이 봤는데, 어떻게 활용해야할지 막막해서 알기만 했던 zip().. 예시로 보니 어떻게 사용해야할지 좀 감이 오는 것 같았다.

func zip<Sequence1, Sequence2>(_ sequence1: Sequence1, _ sequence2: Sequence2) 
-> Zip2Sequence<Sequence1, Sequence2> where Sequence1 : Sequence, Sequence2 : Sequence

함수 정의만 봐서는 좀 어려워 보이는데, 쉽게 말하면 두 시퀀스(컬렉션 형식Array, Set, Dictionary들의 프로토콜)를 합쳐서 튜플로 반환하는 것이다.

튜플? 우리가 많이 썼던 튜플?

맞다, 그래서 맵핑을 안하고 이런 식으로도 사용이 가능하다.

var arr1 = [1,2,3,4]
var arr2 = ["a", "b", "c", "d"]

let result = zip(arr1, arr2)

for (number, string) in result {
    print(number, string)
}

엇 그렇다면 혹시 arr1, arr2의 길이가 다를 때는 에러가 날까?

→ 아니다 그냥 짧은 쪽에 맞춰서 zip()된다고 한다.

  1. map(-)

사실 reduce만 reduce(0, +)이런 식으로 사용할 수 있는줄 알았는데 map도 연산자만 있을 때는 map(-) 이런식으로 trailing closure를 안쓰고 축약할 수 있다는 것을 알았다.

  1. prefix()

자주 사용해야지 하면서 까먹어서 잘 사용하지 않는 prefix()…

func prefix(_ maxLength: Int) -> Self.SubSequence

prefix()또한 반환값이 Self.SubSequence이다.

→ Self.SubSequence가 뭐라고? == Substring, 기존의 String 메모리 재사용!

쨋든, maxLength라는 인자값을 받을 수 있다. index값이 아니라, count라는 것을 기억

어? 근데 index값을 가지고 prefix()를 하고싶을 때는?? 이럴 때를 위해서 prefix(upTo:)가 있다.

func prefix(upTo end: Self.Index) -> Self.SubSequence

upTo:에 들어간 인자를 ‘포함하지 않고’ 그 전까지의 SubSequence를 반환 → stride(to:)와 비슷함.

어 근데 여기서 신기한걸 발견했다.

var arr = [1,2,3,4,5,6]
let subSequence = arr.dropFirst()
let result = subSequence.prefix(upTo: 4)
print(result)
//[2,3,4]

dropFirst()든 split()이든 통해서 subSequence를 반환하고, 그 subSequence를 prefix()했을 때는 갯수가 정확히 나오지 않는다???

고민을 좀 해보니 subSequence가 기존의 String 메모리를 재사용하는데, index가 메모리를 가리키는 주소같은거니까.. index[0]에 해당하는 주소가 없어졌기 때문에 [1,2,3,4] 대신에 [2,3,4]가 출력이 되었구나..! 라고 추론했다.

뭔가 꼬리에 꼬리를 물고 함수들을 판 느낌인데 시간은 많이 걸렸지만 여러가지 애매했던, 새로운 부분들을 알 수 있어서 좋았다!

참조

dropFirst(:), removeFirst(:) 살펴보기

zip(::) | Apple Developer Documentation

Swift ) prefix / suffix

profile
UXUI Design Based IOS Developer

0개의 댓글