[알고리즘] Swift -프로그래머스 연습문제 #160586(대충 만든 자판)

2023. 4. 5. 02:44ALGORITHM/Swift

728x90
반응형

문제링크

 

 

 

 

분석

키 하나에 여러 문자가 할당된 경우 동일한 키를 연속해서 빠르게 누르면 할당된 순서대로 문자가 바뀐다.

예를 들어 1번키에 A B C를 순서대로 문자가 할당되어 있다면 1번 키를 한 번 누르면 A, 두 번 누르면 B, 세 번누르면 C가 되는 식이다.

같은 규칙을 적용 해 아무렇게나 만든 휴대폰 자판이 있다.  이 자판은 키의 개수가 1~100까지 있을 수 있고

특정 키를 눌렀을 때 입력되는 문자들도 무작위로 배열되어 있다.

또 같은 문자가 자판 전체에 여러 번 할당된 경우도 있고, 키 하나에 같은 문자가 여러 번 할당된 경우도 있다.

심지어 아예 할당되지 않은 경우도 있다. 따라서 몇몇 문자열은 작성할 수 없을 수도 있다.

이 자판을 통해 특정 문자열을 작성할 때, 키를 최소한 몇 번 눌러야 문자열을 작성할 수 있는 지 알고 싶다.

1번 키부터 차례대로 할당된 문자들이 순서대로 담긴 배열과 문자열이 담긴 배열이 주어질 때, 문자열을 작성하기 위해 키를 최소한 몇 번 눌러야 하는 지 순서대로 배열에 담아 리턴하는 문제

목표 문자열을 작성할 수 없는 경우에는 -1을 저장

 

풀이 과정

keymap = "ABACD", "BCEFD" 일 때

1번키 1번 A, 2번 B, 3번 A, 4번 C, 5번 D

2번키 1번 B, 2번 C, 3번 E, 4번 F, 5번 D

ABCD 를 입력해야할 경우 1번 + 1번 + 2번 + 5번 = 총 9번이 리턴된다.

 

알파벳별로 딕셔너리에 저장을 해서 몇 번을 눌러야하는 지 저장한다.
동일한 알파벳이 있을 수 있으니 키 값을 알파벳으로 하고 중복된 경우 더 적은 값으로 벨류를 저장한다.
그렇게 해서 순서대로 타켓배열에 있는 알파벳의 벨류값을 더해준다.

 

먼저 딕셔너리를 만들어준다.

for i in 0..<keymap.count {
    let key = Array(keymap[i]).map {String($0)}
    for j in 0..<key.count {
        dic[key[j]] = min(dic[key[j]] ?? 100, j+1)
    }
}

키값은 알파벳으로하고 벨류값은 인덱스 값으로 한다.

중복될 경우 더 적은 값으로 벨류값을 저장한다.

딕셔너리에 이미 있을 없을 경우에는 인덱스의 최대값인 100으로 지정한다.

처음에는 최대값인 100이 아닌 Int.max로 지정했더니 런타임에러가 났다. 

 

for i in 0..<targets.count {
    var count = 0
    let target = Array(targets[i]).map {String($0)}
    for j in 0..<target.count {
        guard dic[target[j]] != nil else {
            count = -1
            break
        }
        count += dic[target[j]]!
    }
    result.append(count)
}

이제 최소값을 구해야한다.

타켓문자열을 딕셔너리에서 찾아서 벨류값을 더해준다.

타켓문자열이 딕셔너리에 없을 경우에는 -1로 넣어주고 반복문을 빠져나온다.

처음에 종료 조건을 못봐서 문제를 틀렸다. 오늘 다시 한번 문제를 잘 읽자는 교훈을 얻는다.

 

 

 

풀이

import Foundation

func solution(_ keymap:[String], _ targets:[String]) -> [Int] {
    var result = [Int]()
    var dic = [String: Int]()
    
    for i in 0..<keymap.count {
        let key = Array(keymap[i]).map {String($0)}
        for j in 0..<key.count {
            dic[key[j]] = min(dic[key[j]] ?? 100, j+1)
        }
    }
    
    for i in 0..<targets.count {
        var count = 0
        let target = Array(targets[i]).map {String($0)}
        for j in 0..<target.count {
            guard dic[target[j]] != nil else {
                count = -1
                break
            }
            count += dic[target[j]]!
        }
        result.append(count)
    }
    
    return result
}

 

결과

print(solution( ["AGZ", "BSSS"]        , ["ASA","BGZ"]         ))

 

 


📂  정리

오랜만에 써보는 딕셔너리

var dic = [String: Int]()

for i in 0..<keymap.count {
    let key = Array(keymap[i]).map {String($0)}
    
    ...
}
var dic = [Character: Int]()

for i in 0..<keymap.count {
    let key = Array(keymap[i])
    
    ...
}

나는 딕셔너리에 string으로 넣기위해서 map으로 변환하여 사용했는 데

String을 Array()에 넣어 Character 배열로 변경할 수 있다.

굳이 map을 사용하지 않고 데이터타입만 변경하면 쉽게 배열을 사용할 수 있다.

 

 

 

 

728x90
반응형