Search
Duplicate

Swift 알고리즘 (2)

Created
2023/10/18 06:39
Tags
CodingTest
태그

Swift 알고리즘 (2)

[실수 다루기]

제곱, 제곱근

import Foundation let x: Int = 5 let sqrtX = sqrt(Double(x)) // 제곱근 let powX = pow(Double(x)) // 제곱 print(Int(sqrtX)) // 2 print(powX) // 25.0
Swift
복사

분수

Int a, Int b의 나눗셈 연산을 해서 Double형 결과를 얻고 싶다면, 반드시 a와 b 모두 Double로 형 변환을 시켜주며 나눗셈 해야한다.
let a: Int = 1 let b: Int = 2 print(a / b) // 0 print(Double(a / b)) // 0.0 print(Double(a) / Double(b)) // 0.5
Swift
복사

[정렬]

조건 정렬

import Foundation let arr = [3, 1, 2, 5, 4] let arr2 = arr.sorted(by: >) // 내림차순 let arr3 = arr.sorted() // 오름차순 struct Student { let name: String let age: Int } let studentArray = [Student(name: "Kim", age: 28), Student(name: "HJ", age: 28), Student(name: "YJ", age: 23)] // 나이 오름차순 정렬 let sortedStudentArray = studentArray.sorted(by: { $0.age < $1.age })
Swift
복사

다중 조건 정렬

튜플의 특성을 이용해서 다중 정렬을 할 수 있다.
(”a”, “1”) < (”b”, “1”) : 첫 번째 원소부터 비교, a < b 이므로 두 번째 원소는 관심 X
(”a”, “1”) < (”a”, “2”) : 첫 번째 원소 비교했으나 같으면 두 번째 원소로 판단
let arr = [["a", "2"], ["a", "1"], ["b", "1"], ["b", "3"], ["b", "2"], ["c", "4"]] print(arr.sorted(by: { ($0[0], $0[1]) < ($1[0], $1[1]) })) // [["a", "1"], ["a", "2"], ["b", "1"], ["b", "2"], ["b", "3"], ["c", "4"]] print(arr.sorted { $0[0] == $1[0] ? $0[1] > $1[1] : $0[0] < $1[0] }) // [["a", "2"], ["a", "1"], ["b", "3"], ["b", "2"], ["b", "1"], ["c", "4"]]
Swift
복사

[반복문 응용]

stride

for i in stride(from: 0, to: 7, by: 2) { print(i) } // 0, 2, 4, 6
Swift
복사

[고차함수]

map, filter, reduce

// 기본 배열 let arr = [1, 2, 3, 4, 5, 6, 7, 8] // <filter> // 짝수만 걸러내기 let evenFilter = arr.filter { (num) -> Bool in return num % 2 == 0 } print(evenFilter) // [2, 4, 6, 8] let evenFilter2 = arr.filter { $0 % 2 == 0 } print(evenFilter2) // [2, 4, 6, 8] // <map> // 문자열 타입으로 바꾸기 let toString = arr.map{ (num: Int) -> String in return "\(num)" } print(toString) // ["1", "2", "3", "4", "5", "6", "7", "8"]\n let toString2 = arr.map { "\($0)" } print(toString2) //[ "1", "2", "3", "4", "5", "6", "7", "8"]\n // <reduce> // 모든 원소를 문자열에 담아 압축하기 let arrStr = arr.reduce ("") { (first, second) -> String in return "\(first)\(second)" } print(arrStr) // "12345678\n" let arrStr2 = arr.reduce("") { "\($0)\($1)" } print(arrStr2) // "12345678\n"
Swift
복사

[순열과 조합]

Combinations (조합)

Python에서는 itertools에서 combinations를 제공해주지만 Swift에서는 제공해주지 않는다.
import Foundation // combination 함수는 제네릭 타입 'T'를 가지며, '[T]' 타입의 배열을 입력으로 받고 'k'라는 정수 // 를 받는다. 반환값은 '[[T]]', 즉, 요소가 'T' 타입의 배열들의 배열 func combination<T>(_ elements: [T], _ k: Int) -> [[T]] { var result = [[T]]() func combi(_ index: Int, _ now: [T]) { if now.count == k { result.append(now) return } for i in index..<elements.count { combi(i + 1, now + [elements[i]]) } } combi(0, []) return result } let arr = [1, 2, 3, 4] let combi = combination(arr, 3) print(combi) // [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
Swift
복사

Permutations (순열)

func permutation<T>(_ elements: [T], _ k: Int) -> [[T]] { // 생성된 모든 가능한 순열이 저장된다 var result = [[T]]() // 각 요소가 이전에 방문한 적이 있는지를 표시한다 var visited = [Bool](repeating: false, count: elements.count) // 재귀적 내부 함수(클로저) // 현재까지 만들어진 순열을 나타내는 now 배열을 매개변수로 받는다 func permut(_ now: [T]) { if now.count == k { result.append(now) return } for i in 0..<elements.count { if visited[i] == true { continue } visited[i] = true permut(now + [elements[i]]) visited[i] = false } } permut([]) return result } let arr = [1, 2, 3, 4] let permu = permutation(arr, 3) print(permu) // [[1, 2, 3], [1, 2, 4], [1, 3, 2], [1, 3, 4], [1, 4, 2], [1, 4, 3], [2, 1, 3], [2, 1, 4], [2, 3, 1], [2, 3, 4], [2, 4, 1], [2, 4, 3], [3, 1, 2], [3, 1, 4], [3, 2, 1], [3, 2, 4], [3, 4, 1], [3, 4, 2], [4, 1, 2], [4, 1, 3], [4, 2, 1], [4, 2, 3], [4, 3, 1], [4, 3, 2]]\
Swift
복사

[기타]

dropLast, popLast, removeLast

보통 Array를 스택으로서 하용할 때 활용
dropLast(n) : Array를 변경하지는 않고, 마지막 n개를 제외한 원소들을 반환
popLast() : Array의 마지막 원소를 제거해버리고, 남은 원소들 반환, 원소가 비어있을 시 nil 반환
removeLast(n) : Array의 마지막 원소 n개를 제거해버리고, 남은 원소들을 반환, 원소가 비어있을 시 컴파일 에러
import Foundation // 시간 측정 메서드 public func progressTime(_ closure: () -> ()) -> TimeInterval { let start = CFAbsoluteTimeGetCurrent() closure() let diff = CFAbsoluteTimeGetCurrent() - start return (diff) } // 긴 배열 var arr = [Int](repeating: 0, count: Int(pow(10.0, 6))) // arr의 마지막 4개의 원소를 pop한 배열의 결과를 얻고 싶다 // 1. dropLast 한 것을 대입 -> 0.35초 progressTime { let arr2 = arr.dropLast(4) } // 2. index 슬라이싱 대입 -> 0.32초 progressTime { let arr2 = arr[arr.startIndex..<arr.index(arr.startIndex, offsetBy: arr.endIndex - 4)] } // 3. popLast() 4번 -> 0.0002초 progressTime { arr.popLast() arr.popLast() arr.popLast() arr.popLast() } // 4. removeLast(4) -> 0.0007초 progressTime { arr.removeLast(4) }
Swift
복사

결론

popLast() 또는 removeLast() 가 훨씬 빠르다
popLast() 쓰자

split vs components

문자열을 분리하는 split과 components의 차이점
성능은 split가 더 빠르기 때문에 웬만하면 split 쓰기
import Foundation var str = "a b c d e" var str2 = "a b c d e" print(str.split(separator: " ")) // ["a", "b", "c", "d", "e"] print(str.components(separatedBy: " ")) // ["a", "b", "c", "d", "e", ""] print(str2.split(separator: " ")) // ["a", "b", "c", "d", "e"] print(str2.components(separatedBy: " ")) // ["a", "", "b", "", "c", "", "d", "", "e"]
Swift
복사

백준 풀 때 입력 빨리받기

백준에서 이걸 쓰면 시간초가 안나는 경우가 상당히 많다.
파이썬의 sys.stdin.readline() 역할이라고 생각하면 된다.
File 입력이라 Xcode 콘솔 상에서 테스트하긴 힘들다
import Foundation final class FileIO { private let buffer:[UInt8] private var index: Int = 0 init(fileHandle: FileHandle = FileHandle.standardInput) { buffer = Array(try! fileHandle.readToEnd()!)+[UInt8(0)] // 인덱스 범위 넘어가는 것 방지 } @inline(__always) private func read() -> UInt8 { defer { index += 1 } return buffer[index] } @inline(__always) func readInt() -> Int { var sum = 0 var now = read() var isPositive = true while now == 10 || now == 32 { now = read() } // 공백과 줄바꿈 무시 if now == 45 { isPositive.toggle(); now = read() } // 음수 처리 while now >= 48, now <= 57 { sum = sum * 10 + Int(now-48) now = read() } return sum * (isPositive ? 1:-1) } @inline(__always) func readString() -> String { var now = read() while now == 10 || now == 32 { now = read() } // 공백과 줄바꿈 무시 let beginIndex = index-1 while now != 10, now != 32, now != 0 { now = read() } return String(bytes: Array(buffer[beginIndex..<(index-1)]), encoding: .ascii)! } @inline(__always) func readByteSequenceWithoutSpaceAndLineFeed() -> [UInt8] { var now = read() while now == 10 || now == 32 { now = read() } // 공백과 줄바꿈 무시 let beginIndex = index-1 while now != 10, now != 32, now != 0 { now = read() } return Array(buffer[beginIndex..<(index-1)]) } } /* Usage // stdin Input: 1 import Foundation let fIO = FileIO() let n = fIO.readInt() print(n) // 1 /*
Swift
복사

[기억해둘 것]

1.
Set에는 튜플이 들어갈 수 없다
a.
Set<(Int, Int)> 는 불가능하다
2.
split(separator: “ “) 대신 split{$0 == “ ”} 을 쓰자
var str = "1 2 3" let arr = str.split(separator: " ").map{ Int(String($0))! } let arr2 = str.split{ $0 == " " }.map{Int(String($0))! }
Swift
복사

 Reference