1️⃣ 문제

문제 - 조이스틱

풀이참조 - Blog

2️⃣ 풀이 방법 및 코드

해당 문제는 그리디 유형이지만, 최근에 올라온 반례의 테스트 케이스로 완전 탐색 풀이로 풀었다.

  1. 알파벳을 바꾸는 up, down은 따로 각 인덱스 마다 아스키 코드 차이 값을 이용해서 up과 down 두 방향으로 알파벳 조정 시 min값을 구하고 더해주었다.

  2. 연속되는 A 구간이 많다면, A 이전까지 갔다가 다시 돌아와서 뒤로 가서 수정하는 방법이 커서 횟수가 적을 수가 있다.

    1. 기본값은 오른쪽으로 한칸씩 이동하는 name.count - 1

    2. 특정 인덱스 다음부터 A가 있다면, 끝나는 A 지점 찾아주기

    3. 문자열 각 특정 인덱스를 기준으로 오른쪽으로 해당 인덱스까지 갔다가 다시 돌아와서 A 끝나는 구간으로 뒤로 가는 방법과,

      A 끝나는 구간으로 먼저 뒤로 갔다가 다시 원점 돌아와서 해당 인덱스까지 가는 방법의 커서 횟수를 구하고

    4. 미리 구한 좌우 이동 커서 횟수와 이들을 비교해 작은 값으로 새로 저장해준다.

  3. 업다운과 좌우 더해준 값을 리턴하면 끄읕@!

소스 코드

import Foundation

func solution(_ name:String) -> Int {
    var name = Array(name)
    
    // 1. 알파벳 조정
    let upDown = name.map {
        let upCnt = Int($0.asciiValue! - 65)
        let downCnt = Int(90 - $0.asciiValue! + 1)
        return min(upCnt, downCnt)
    }.reduce(0, +)
    
    // 2. 커서 이동 횟수
    var leftRight = name.count - 1  // 2-1
    name.enumerated().forEach {
        // 2-2
      	var endA = $0.0 + 1
        while endA < name.count && name[endA] == "A" {
            endA += 1
        }
        
        // 2-3
      	let leftFirstCnt = $0.0 * 2 + (name.count - endA)
        let rightFirstCnt = (name.count - endA) * 2 + $0.0
        let move = min(leftFirstCnt, rightFirstCnt)
      
      	// 2-4
        leftRight = leftRight < move ? leftRight: move
    }
    
  	// 3
    return upDown + leftRight
}