azhy의 iOS 이야기

[iOS] swift 알고리즘, 코딩테스트에 필요한 tip 정리 본문

iOS

[iOS] swift 알고리즘, 코딩테스트에 필요한 tip 정리

azhy 2024. 11. 8. 08:56

2022년 5월 6일에 작성됨

 

기본 입력받기

// return String
var input = readLine()!

// return Int
var input = Int(readLine()!)!

"1 2 3 4 5"와 같은 공백 있는 숫자 입력받기

// split - return: [SubString] 
var nums = readLine()!.split(separator: " ").map {Int($0)!} 

// components - return: [String] -> import Foundation 필수
var nums = readLine()!.components(separatedBy: " ").map {Int($0)!}

// FileIO, 입력받으면서 리스트에 바로 추가하기
array.append((file.readInt(), file.readInt()))

"12345"와 같은 공백 없는 숫자를 배열로 입력받기

// Int
var nums = Array(readLine()!).map {Int(String($0))!}

// String
var nums = Array(readLine()!).map {String($0)}

// FileIO
let nums = [file.readInt(), file.readInt()]

입력값 시간초과 -> fread의 swift 버전 (라이노님 FileIO)

github

보통 입출력이 10~20만 줄 넘어가면 쓰는 걸 추천
xcode 터미널에서 엔터가 아닌 EOF를 입력해야 입력 완료가 되고, 터미널에서 값을 입력한 뒤 제일 마지막에 Ctrl + D를 입력하면 출력값이 나옵니다.

prefix / suffix

let strData = "hello성훈!!"

// [prefix : 시작 기준으로 지정한 문자 개수 출력]
let startData = strData.prefix(5)
print(startData)  // hello

// [suffix : 종료 기준으로 지정한 문자 개수 출력]
let endData = strData.suffix(4)
print(endData) // 성훈!!


let numbers = [1, 2, 3, 4, 5]
print(numbers.prefix(2))
// Prints "[1, 2]"
print(numbers.prefix(10))
// Prints "[1, 2, 3, 4, 5]"

let numbers = [1, 2, 3, 4, 5]
print(numbers.suffix(2))
// Prints "[4, 5]"
print(numbers.suffix(10))
// Prints "[1, 2, 3, 4, 5]"

split(whereSeparator: {})

/// 기준이 되는 문자를 제외한 요소를 배열로 만들어 리턴
let dartResult = "1S2D*3T"
var scores = dartResult.split(whereSeparator: {!$0.isNumber}).map {Int($0)!}
print(scores)
// Prints "[1, 2, 3]"
let letters = dartResult.split(whereSeparator: {$0.isNumber})
print(letters)
// Prints "["S", "D*", "T"]"

subString

// 3번째부터 끝까지
let startIdx: String.Index = str.index(str.startIndex, offsetBy: 3)
var result = String(str[startIdx...])

// 처음부터 3번째까지
let endIdx: String.Index = str.index(str.startIndex, offsetBy: 3)
var result = String(str[...endIdx])

문자열 반복

let str = String(repeating: "ㅋ", count: 10)
print(str) // "ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ"

문자열에 특정 문자 바꾸기

// import Foundation 필수
let str = "ung!chun!"
let str2 = str.replacingOccurrences(of: "!", with: "?")
print(str2) // ung?chun?

개행 없는 print

print("Hello", terminator:"")

forEach

let nums: [Int] = [1, 2, 3, 4]

nums.forEach {
	print($0) // 1 2 3 4
}

stride

// 3 6 9
for i in stride(from: 3, to: 12, by: 3) {
    print(i)
}

// 3 6 9 12
for i in stride(from: 3, through: 12, by: 3) {
    print(i)
}

절댓값

// 11
abs(-11)

제곱

let value = 3.0 

// 9.0
pow(value, 2)

제곱근 구하기

let value = 9.0

// 3.0
sqrt(value)

자릿수 더하기

// n = 123, return = 6
String(n).map{ String($0)}.reduce(0){ $0 + Int($1)! }

배열 요소에 접근하기

var array = [1, 2, 3, 4, 5]

// [2, 3, 4]
array[1...3]

배열에 요소 추가하기

var array = [1, 2, 3]

array.append(4) // [1, 2, 3, 4]
array.append(contentsOf: [5, 6, 7]) // [1, 2, 3, 4, 5, 6, 7]

배열에 원하는 값 index 찾아서 삭제하기

if let index = array.firstIndex(where: {$0 == value}) {
	array.remove(at: index)
}

1차원 배열 선언

let arr = [Int]() 

let arr = Array(repeating: 0, count: 5) 
let arr = [Int](repeating: 0, count: 5)

2차원 배열 선언

let arr = [[Int]]() 

let arr = Array(repeating: Array(repeating: 0, count: 3), count: 5) 
let arr = [[Int]](repeating: [Int](repeating: 0, count: 3), count: 5)

map

var string = ["1","2","3","4"]

// [1,2,3,4] 각 원소를 전부 Int로 맵핑
string.map { Int($0)! }

filter

var array = [1,2,3,4]

// [2,4] 조건에 맞는 수만 뽑아냄
array.filter { $0 % 2 == 0 }

reduce

// 초깃값이 3이고 정수 배열의 모든 값을 더하는 코드
let numbers: [Int] = [1, 2, 3]
var sumFromThree: Int = numbers.reduce(3) {
    print("\($0) + \($1)")
    // 3 + 1
    // 4 + 2
    // 6 + 3
    return $0 + $1
}
print(sumFromThree) // 9

// 간단하게는 이렇게도 가능하긴함
var array = [1,2,3,4]

// 숫자 합이 나타남. 문자열 합치기도 가능
array.reduce(0, +) 
// 문자열 합치기는 joined()를 사용하자. reduce가 훨씬 느림

joined()

joined는 배열의 문자열들을 하나의 문자열로 반환하는 것이기 때문에 배열의 요소들이 문자열 이어야 합니다.

var brands = ["Dell", "HP", "Apple"]

// DellHPApple
var result1 = brands.joined()

// Dell HP Apple
var result2 = brands.joined(separator:" ")

// Dell, HP, Apple
var result3 = brands.joined(separator:", ")

// 만약 문자열이 아니라면 문자열로 바꾸고 진행해야함
var result: [Int] = [1, 2, 3, 4]
result.map{String($0)}.joined() // [1, 2, 3, 4] -> 1234
result.map{String($0)}.joined(separator: ", ") // [1, 2, 3, 4] -> 1, 2, 3, 4

flatMap(), compactMap()

let array1 = [1, nil, 3, nil, 5, 6, 7]
let flatMapTest1 = array1.flatMap{ $0 }
let compactMapTest1 = array1.compactMap { $0 }

// flatMapTest1 : [1, 3, 5, 6, 7]
// compactMapTest1 : [1, 3, 5, 6, 7]

 

1차원 배열에서는 둘 다 동일한 결과를 나타내지만 Swift 4.1부터는 1차원 배열에서 nil을 제거하고 옵셔널 바인딩을 하고 싶을 때는 flatMap 말고 compactMap을 사용하라고 합니다.

let array2: [[Int?]] = [[1, 2, 3], [nil, 5], [6, nil], [nil, nil]]
let flatMapTest2 = array2.flatMap { $0 }
let compactMapTest2 = array2.compactMap { $0 }

// flatMapTest2 : [Optional(1), Optional(2), Optional(3), nil, Optional(5), Optional(6), nil, nil, nil]
// compactMapTest2 : [[Optional(1), Optional(2), Optional(3)], [nil, Optional(5)], [Optional(6), nil], [nil, nil]]

 

flatMapt과 compactMap은 nil을 제거하지 않고 1차원 배열일 때만 nil 제거

flatMap은 2차원배열을 1차원배열로 flatten 하게 만들어주는 반면, compactMap은 1차원 배열로 만들지 않습니다.

2차원 배열을 1차원으로 만들 때는 flatMap 사용

let array2: [[Int?]] = [[1, 2, 3], [nil, 5], [6, nil], [nil, nil]]
let flatMapTest2 = array2.flatMap { $0 }.compactMap{ $0 }

// flatMapTest2 : [1, 2, 3, 5, 6]

 

flatMap으로 flatten 하게 만들고 compactMap으로 처리하면 편하게 2차원 배열을 옵셔널 바인딩 한 1차원 배열로 출력 가능

let array3 = [[[1], [2, 3], [4, 5, 6], [7, 8, 9, 10]]]

let flatMapTest3 = array3.flatMap { $0 }
// [[1], [2, 3], [4, 5, 6], [7, 8, 9, 10]]

let doubleflatMapTest3 = flatMapTest3.flatMap { $0 }
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

 

3차원 배열도 flatMap 2번 사용하면 flatten 하게 처리 가능

Set

정렬되지 않은 컬렉션

중복 허용 x

해시를 통해 값을 저장해서 배열에 비해 검색 속도가 빠름 (저장되는 자료형은 Hashable 프로토콜 준수해야 함)

// 생성
var tempSet: Set<Int> = []
var tempSet = Set<Int>()

var tempSet: Set<Int> = [1, 2, 5, 0]

let count: Int = tempSet.count            // Set 갯수 확인 : 4
let isEmpty: Bool = tempSet.isEmpty       // Set 비었는지 확인 : false

tempSet.contains(1)                    // true
tempSet.contains(10)                   // false

// insert : 값을 추가하고, 추가된 결과를 튜플로 리턴 (중복이면 false, 추가된 값)
tempSet.insert(1)                // (false, 1)
tempSet.insert(10)               // (true, 10)
 
// update : 값이 존재하지 않으면 추가 후 nil 리턴, 존재할 경우 덮어쓰기 후 덮어쓰기 전 값 리턴
tempSet.update(with: 1)          // Optioanl(1)
tempSet.update(with: 120)        // nil

// remove() : 한 가지 요소 삭제할 때 사용, 삭제 후 삭제한 값 return (없는 요소 삭제 시 nil 리턴)
tempSet.remove(1)              // Optional(1)
tempSet.remove(10)             // nil
 
// removeAll() : 전체 요소 삭제
tempSet.removeAll()

dictionary

// 생성
var dict: [String: Int] = [:]  
var dict = [String: Int]()

// 갯수 확인
let count: Int = dict.count
let isEmpty: Bool = dict.isEmpty

var dict = ["height": 165, "age" : 100]

let height = dict["height"] // Optional(165)
let weight = dict["weight"] // nil

dict["weight"] = 100 // 해당 Key가 없다면, 추가 (insert)
dict["height"] = 200 // 해당 Key가 있다면, Value 덮어쓰기 (update)                                

dict["weight"] = nil // 해당 Key가 없어도 에러 안남
dict["height"] = nil // 해당 Key가 있다면, 해당 Key-Value 삭제
dict.removeAll() // 전체 삭제

dict.keys // "height, "age"
dict.keys.sorted() // "age", "height

dict.values // 165, 100
dict.values.sorted() // 100, 165

dict.sorted(by: {$0.value > $1.value})

dict.filter(condition) // 해당 클로저를 만족하는 요소만 모아서 새 딕셔너리로 리턴 

var v = [[Int]]()
var xDic = [Int: Int]()
xDic[v[i][0]]
let x = xDic.filter {$0.value < 2}.keys
ans.append(contentsOf: xDic.values.filter {$0 < 2})

2차원 배열 정렬하기

var arr = [[0, 3], [1, 9], [2, 6]]
let sortedArray = arr.sorted(by: {$0[1] < $1[1] }) // 각 배열 두 번째 수 기준으로 오름차순
let sortedArray = arr.sorted(by: {$0.1 < $1.1 }) // 같은 결과
print(sortedArray) // [[0, 3], [2, 6], [1, 9]]

init (repeating: count: )

// 수박수박수박수박
let watermelon4 = String(repeating: "수박", count: 4)
print(watermelon4)

// [false, false, false, false, false]
let liar = Array(repeating: false, count: 5)
print(liar)

 

배열 안에 담긴 숫자만큼 일일이 print 하면 매번 print 하는 것도 상당히 느리기 때문에 시간초과 되는 경우가 많은데

String - init ( repeating: count: )로 한 번에 만들어서 String에 저장해서 출력하면 시간초과를 막을 수 있습니다.

var answer = ""
// \n 이용해서 한 줄에 하나씩 출력
answer += String(repeating: "\(value)\n", count: countValue)
// 공백 이용해서 한 줄에 띄어서 출력
answer += String(repeating: "\(value) ", count: countValue)
// 한 줄에 붙여서 출력
answer += String(repeating: "\(value)", count: countValue)
print(answer)

최대공약수, 최소공배수

// 최대공약수
func GCD(_ a: Int, _ b: Int) -> Int {
    let mod: Int = a % b
    return 0 == mod ? min(a, b) : GCD(b, mod)
}

// 최소공배수
func LCM(_ a: Int, _ b: Int) -> Int {
    return a * b / GCD(a, b)
}

heap / 우선순위 큐

MinHeap - 블로그

순열과 조합

블로그

 

'iOS' 카테고리의 다른 글

[iOS] Font 추가하기  (2) 2024.11.11
[iOS] github에 API Key 숨기기  (0) 2024.11.11
[iOS] 앱 기본 언어 한국어로 변경하는 법  (1) 2024.11.11
[iOS] 다사다난했던 첫 앱 출시 후기  (5) 2024.11.11
[iOS] GCD, Dispatch Queue  (0) 2024.11.08