프로그래머스 모의테스트 Swift 풀이

# 문제출처 : 프로그래머스 모의테스트 페이지

https://programmers.co.kr/learn/courses/18

# 파트1. 자릿수 더하기 문제

https://programmers.co.kr/learn/courses/18/lessons/1876

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import Foundation

func solution(_ n:Int) -> Int
{
    var answer:Int = 0
    
    let input = String(n)
    for c in input {
        answer += Int(String(c))!
    }
    
    // 또는
    // answer = input.map({ Int(String($0))! }).reduce(0) { $0 + $1 }
    return answer
}

# 파트2. 순열 검사 문제

https://programmers.co.kr/learn/courses/18/lessons/1877

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import Foundation

func solution(_ arr:[Int]) -> Bool {
    var answer = true
    // 빠른 탐색을 위해 배열을 정렬
    let newArr = arr.sorted()
    
    for i in 0..<newArr.count {
        // 중간에 false가 뜨면 더 이상 탐색하지 않고 종료
        if answer == false {
            break
        }
        
        // contains는 느리므로 배열값을 i와 바로 비교
        if newArr[i] != (i + 1) {
            answer = false
        }
    }
    
    return answer
}

# 파트3. 나머지 한 점 문제

https://programmers.co.kr/learn/courses/18/lessons/1878

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import Foundation

func solution(_ v: [[Int]]) -> [Int]
{
    var answer = [Int]()
    
    let setA = v[0]
    let setB = v[1]
    let setC = v[2]
    
    // A와 B가 같으면 D는 C와 동일
    // A와 C가 같으면 D는 B와 동일
    // 같은게 없으면 D는 A와 동일
    
    // 앞의 점 구하기
    if (setA[0] == setB[0]) {
        answer.append(setC[0])
    } else if (setA[0] == setC[0]) {
        answer.append(setB[0])
    } else {
        answer.append(setA[0])
    }
    
    // 뒤의 점 구하기
    if (setA[1] == setB[1]) {
        answer.append(setC[1])
    } else if (setA[1] == setC[1]) {
        answer.append(setB[1])
    } else {
        answer.append(setA[1])
    }
    
    return answer
}

# 파트4. 가장 큰 정사각형 찾기 문제

https://programmers.co.kr/learn/courses/18/lessons/1879

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import Foundation

func solution(_ board:[[Int]]) -> Int
{
    var newBoard = board
    
    let row = newBoard.count
    let col = newBoard[0].count
    var answer = 0
    
    // 행이나 열의 길이가 2 미만이라면 직접 돌리면서 1이 하나라도 있는지 체크
    // 하나라도 있으면 통과.
    if (col < 2 || row < 2) {
        for i in 0 ..< row {
            for j in 0 ..< col {
                if newBoard[i][j] == 1 {
                    answer = 1
                }
            }
        }
    } else {
        // 배열의 [1][1]부터 반복문을 돌린다. (첫 번째 행, 첫 번째 열 무시)
        // 현재 값이 1일 경우, 좌측값, 상단값, 좌측상단값 중
        // 가장 작은 값의 +1 한 값을 현재 값으로 할당
        for i in 1 ..< row {
            for j in 1 ..< col {
                if newBoard[i][j] == 1 {
                    newBoard[i][j] = min(newBoard[i - 1][j], newBoard[i][j - 1], newBoard[i - 1][j - 1]) + 1
                    if newBoard[i][j] > answer {
                        answer = newBoard[i][j]
                    }
                }
            }
        }
    }
    return answer  - answer
}

# 파트5. 땅따먹기 문제

https://programmers.co.kr/learn/courses/18/lessons/1880

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import Foundation

func solution(_ land:[[Int]]) -> Int{
    var answer = 0
    var newLand = land
    
    for i in 1 ..< newLand.count {

        newLand[i][0] += max(newLand[i - 1][1], newLand[i - 1][2], newLand[i - 1][3])
        newLand[i][1] += max(newLand[i - 1][0], newLand[i - 1][2], newLand[i - 1][3])
        newLand[i][2] += max(newLand[i - 1][0], newLand[i - 1][1], newLand[i - 1][3])
        newLand[i][3] += max(newLand[i - 1][0], newLand[i - 1][1], newLand[i - 1][2])
    }
    answer = (newLand.last?.max())!
    
    return answer
}

# 파트6. 스티커 모으기 문제

https://programmers.co.kr/learn/courses/18/lessons/1881

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import Foundation

func solution(_ sticker:[Int]) -> Int{
    
    // 예외처리
    if sticker.count == 0 { return 0 }
    if sticker.count == 1 { return sticker[0] }
    
    var dp1 = [Int]()    // 첫번째 뜯은 경우
    var dp2 = [Int]()    // 첫번째 안뜯은 경우
    // 첫번째 뜯은 경우 첫번째는 스티커값
    dp1.append(sticker[0])
    dp1.append(dp1[0])
    
    // 첫번째 안뜯은 경우 첫번째는 0, 두번째는 스티커값
    dp2.append(0)
    dp2.append(sticker[1])

    // 스티커가 원형인걸 반영하기 위해 탐색범위를 다르게 함
    if sticker.count > 2 {
        // 첫번째를 뜯었으면 n-1을 뜯으면 안되므로 n-2까지 탐색
        for i in 2 ... sticker.count - 2 {
            // 하나 건너뛰어서 스티커를 떼는게 나은지 다음 스티커를 기다릴지 판정
            let value = max(dp1[i-2] + sticker[i], dp1[i-1])
            dp1.append(value)
        }
        
        // n-1까지 탐색
        for i in 2 ... sticker.count - 1 {
            let value = max(dp2[i-2] + sticker[i], dp2[i-1])
            dp2.append(value)
        }
    }
    
    return max(dp1.max()!, dp2.max()!)
}

# 파트7. 단어 퍼즐 문제

https://programmers.co.kr/learn/courses/18/lessons/1882

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import Foundation

func solution(_ strs:[String], _ t:String) -> Int {
    
    let INF = 9999
    let wordLength = t.count

    // 고속탐색을 위한 해시셋 생성
    let strsSet = Set(strs.map { $0 })
    // 고속탐색을 위한 스트링셋 생성
    let splitT = t.map { String($0) }
    
    // 각 자리에서 사용가능한 단어조각 최소값 저장을 가장 큰값으로 저장한 배열을 생성
    // dp[i] = min(dp[i+1],dp[i+2],dp[i+3],dp[i+4]) + 1
    var dp = [Int](repeating: INF, count: wordLength)
    dp.append(0)

    
    // 각자리별로 사용 가능한 단어조각의 최소값을 뒷자리부터 계산
    for i in (0 ..< wordLength).reversed() {
        // 단어조각 최대 길이는 5
        for j in 0 ..< 5 {
            let k = i + j + 1
            // 검색 인덱스를 넘어가면 종료
            if k > wordLength {
                break
            }
            
            // 사용가능한 단어가 있는지 확인
            // Swift의 String.index는 쓰기는 편하지만 매우 느리다
            // let availWord = String(t[t.index(t.startIndex, offsetBy: i)..<t.index(t.startIndex, offsetBy: k)])
            // 그래서 단어매치를 할땐 배열로 직접 가져와서 해시셋과 비교해야 된다
            // strsSet과 비교할 단어를 생성
            var availWord = String()
            for idx in i ..< k {
                availWord += splitT[idx]
            }
            
            // 조합이 가능하면 dp[i]의 값을 최소값으로 갱신
            if (strsSet.contains(availWord) && dp[i + j + 1] != INF) {
                dp[i] = min(dp[i], dp[i + j + 1] + 1)
            }
        }
    }
    
    // 단어를 조합해서 만들 수 없으면 -1 반환, 아니면 dp[0] 반환
    if dp[0] == INF { return  -1 }
    return dp[0]
}
Built with Hugo
Theme Stack designed by Jimmy