일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- ac swift 풀이
- ac 투포인터
- swift ac 풀이
- iOS Charts
- swift 2xn 타일링
- ios
- rxswift
- 백준 2xn 타일링 풀이
- swift
- swift 알고리즘
- swift gRPC
- 백준 2xn 타일링
- swift ac
- swift 백준 9095
- 연속된 부분 수열의 합 swift
- swift 2xn 타일링 백준
- 123 더하기 풀이
- swift 연속된 부분 수열의 합
- swift 프로그래머스
- ac 구현 풀이
- swift dfs
- swift 2xn 타일링 풀이
- swift 9095 풀이
- 1 2 3 더하기 풀이
- swift 연속된 부분 수열의 합 풀이
- 연속된 부분 수열의 합 투포인터
- swift algorithm
- swift ac 문제풀이
- swift codility
- MVVM
- Today
- Total
boraBong
[Swift] 조이스틱 문제 풀이 [Programmers - Level2] 본문
💬 문제
https://school.programmers.co.kr/learn/courses/30/lessons/42860
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
- 처음엔 그리디 유형의 문제라고 해서 어떻게든 간단한 풀이방법을 찾아내려고 했습니다.
그렇지만 최선의 결과를 도출하려면 이동의 경우의 수를 모두 파악하고 계산할 필요가 있었습니다.
순간 재귀로 풀까 하는 생각이 들어서, 그리디로 풀이하는 힌트를 얻고자 질문하기에 들어갔는데 사람들이 화가 많이 나있었어요 ! ㅋㅋㅋㅋㅋㅠㅠㅠ 넘 공감... - 질문하기를 살펴보니 그리디로는 최소 이동 횟수를 파악하기 힘든 문제였습니다. 따라서 dfs(재귀)를 이용해서 풀이해주었습니다.
- 그리디로는 왼쪽, 오른쪽 둘다 이동하는 경우를 도출하기 어렵기 때문인 것 같아요. 그럼에도 그리디로 푸신 분들이 있더라고요 .. 존경스럽습니다,,!!
💬 Idea
- 조이스틱을 상하로 이동시켜 알파벳을 만들어줄 때 알파벳별 최소 이동횟수를 미리 저장해준다.
- 알파벳 O부터는 Z부터 거슬러올라가는 것이 더 빠르므로 Unicode.Scalar를 응용하여 A~N / O~Z 의 경우를 나누어서 최소 이동횟수를 abcDict에 저장해주었다.
- 완성해야하는 name의 첫 번째 알파벳이 “A”가 아니라면 조이스틱으로 이동시켜 첫 번째 알파벳을 만들어준다.
- 이후 첫 번째 커서 위치에서(0) dfs를 수행한다.
- 오른쪽 으로 이동하여 도달할 수 있는 A가 아닌 알파벳을 찾아 dfs를 수행한다. (재귀)
- 왼쪽 으로 이동하여 도달할 수 있는 A가 아닌 알파벳을 찾아 dfs를 수행한다. (재귀)
- 이렇게 오른쪽, 왼쪽 모두 이동하며 얻게 되는 최소 카운트를 res에 저장하고 함수를 종료한다.
- 결과를 도출할 때 첫 번째 알파벳을 만들어주기 위해 이동시켰던 횟수만큼을 더해준다.
💬 풀이
import Foundation
func solution(_ name:String) -> Int {
var abcDict: [String: Int] = [:]
let name = name.map({ String($0) })
var initialName = Array(repeating: "A", count: name.count)
var res = Int.max
for i in 1...26 {
if let scalar = Unicode.Scalar(64 + i) {
if i <= 14 {
abcDict[scalar.description] = i - 1
} else {
abcDict[scalar.description] = abs(i - 26) + 1
}
}
}
//"A": 0, B": 1, "C": 2, "D": 3, "E": 4, "F": 5, "G": 6, "H": 7, "I": 8, "J": 9, "K": 10, "L": 11, "M": 12, "N": 13, "O": 12, "P": 11, "Q": 10, "R": 9, "S": 8, "T": 7, "U": 6, "V": 5, "W": 4, "X": 3, "Y": 2, "Z": 1
if name[0] != "A" {
initialName[0] = name[0]
}
/// dfs
func dfs(_ initialName: [String], _ count: Int, _ cursor: Int) {
if initialName == name {
res = min(res, count)
return
}
// right
let right = joystickMovesLeftorRight(true, cursor, name, initialName)
var rightName = initialName
var rightCount = count
rightName[right[0]] = name[right[0]]
rightCount += abcDict[name[right[0]]]! + right[1]
dfs(rightName, rightCount, right[0])
// left
let left = joystickMovesLeftorRight(false, cursor, name, initialName)
var leftName = initialName
var leftCount = count
leftName[left[0]] = name[left[0]]
leftCount += abcDict[name[left[0]]]! + left[1]
dfs(leftName, leftCount, left[0])
}
dfs(initialName, 0, 0)
return name[0] != "A" ? res + abcDict[name[0]]! : res
}
// MARK: - 조이스틱 좌/우로 이동 후 커서와 이동횟수를 반환하는 메서드
func joystickMovesLeftorRight(_ isRight: Bool, _ cursor: Int, _ name: [String], _ initialName: [String]) -> [Int] {
var cursor = cursor
var moves = 0
for _ in name {
cursor = isRight ? cursor + 1 : cursor - 1 // 오른쪽으로 커서 이동시 + 1 / 왼쪽으로 커서 이동시 - 1
moves += 1 // 이동횟수는 어떤 경우든 + 1
if cursor > name.count - 1 {
cursor = 0
}
if cursor < 0 {
cursor = name.count - 1
}
// 찾아야하는 알파벳: A가 아니면서 아직 변환되지 않은 것
if name[cursor] != "A" && initialName[cursor] == "A" {
break
}
}
return [cursor, moves]
}
근데.. 풀이 후 실행을 시켜봤는데 테스트케이스 7번만 실패가 떴어요... !
40이 최소횟수가 아닌가…? 기댓값이 왜 더 크지 😅😅 함수 설계 잘못했나 아찔했습니다..
이게 실패해서 공책에다 테스트케이스 직접 계산해봤는데,, 최소가 40이 맞는 것 같아서 제출을 해보았습니다.
이게 웬걸..? ㅋㅋㅋㅋㅋ 정확성이 맞네요,,,,?
혼돈의 조이스틱.. 문제 갖고오면서 설명에서 빠뜨린 조건이 있는걸까요,,?
테스트 7번 정답이 42인 이유가 궁금합니다.....
[테스트 7번 최소 이동로직]
JAANAAAAN (name)
AAAAAAAAA (initial)
1. 첫번째 알파벳 A -> J 로 변경 JAAAAAAAA (+9) 2. 인덱스 0에서 왼쪽으로 커서를 이동시켜 끝 인덱스에 위치한 N으로 이동 (+1) A -> N 변경 (+13) 3. 마지막 인덱스에서 오른쪽으로 커서를 이동시켜 인덱스 3의 N으로 도달 (+4) A -> N 변경 (+13) |
= 9 + 1 + 13 + 4 + 13 = 40
제가 생각한 로직은 이러해서 40이 도출되었는데, 혹시 이상한 부분이 있다면 댓글로 알려주시면 감사하겠습니다..!!
GitHub - hwangJi-dev/swiftAlgorithm: Algorithm Practice with Swift
Algorithm Practice with Swift. Contribute to hwangJi-dev/swiftAlgorithm development by creating an account on GitHub.
github.com
'iOS > Algorithm' 카테고리의 다른 글
[Swift] 9095번: 1, 2, 3 더하기 문제 풀이 [BOJ - Silver3] (2) | 2023.04.06 |
---|---|
[Swift] 삼각 달팽이 문제 풀이 [Programmers - Level2] (2) | 2023.04.05 |
[Swift] 불량 사용자 문제 풀이 [Programmers - Level3 (2019 카카오 개발자 겨울 인턴십)] (0) | 2023.04.03 |
[Swift] 7576번: 토마토 문제 풀이 [BOJ - Gold5] (0) | 2023.04.02 |
[Swift] 2178번: 미로 탐색 문제 풀이 [BOJ - Silver1] (2) | 2023.04.01 |