알고리즘 문제 풀이

[프로그래머스] 조이스틱 Swift (Greedy)

lgvv 2021. 8. 8. 16:54

✅이번에는 조이스틱 문제에 대해서 알아보자.

코테 시작한지 얼마 안되서 아직도 어려움.. ㅜ

 

문제를 보자마자, 어..? 이건 쉽다...! 했었는데 막상 풀다보니까 무언가 잘못됨을 느낌.

일단 우로 이동만 있고, 좌로 이동하는 것에 대하여 이해를 아예 못했었는데, 다시 몇번 풀면서 나중에야 이해가 됨 ㅠㅠ

 

🔸 이 포스팅에서 주의깊게 봐야하는 점.

✅문자열을 map을 이용하여 name[0]으로 참조하는 기술

✅문자를 아스키코드로 바꾸는 법

✅코테용 사고방식 : 슬슬 느낌이 오기 시작했다...!

 

알고리즘 자체가 어렵지는 않다.

특히 상하 컨트롤 하는 경우는 이동의 값이 고정적인 부분이라 아주아주 쉬웠다.

 

상하컨트롤에 대한 횟수계산

 

✅코드

 

/* 조이스틱
 https://programmers.co.kr/learn/courses/30/lessons/42860
 */

import Foundation

func solution(_ name:String) -> Int {

    // 알파벳갯수 : 총 26개
    // ascii코드 이용하면 좋겠다. A -> 65 , Z -> 90
    var ans = 0
    var move = 0
    var minMove = name.count - 1
    let name = name.map( {$0} ) // 문자열을 배열형식으로 취하기 위함
    var current = 0
    
    for char in name { // 문자 하나하나가 분리되어 실행돼 -> 우로 이동을 가정
        let value = Int(char.asciiValue!)
        // 상하 컨트롤 횟수 -> 고정
        if value == 65 {
            // counting X
        }
        else if value <= 78 {
            ans += (value-65) // 상하 컨트롤
        } else {
            ans += (91-value) // 상하 컨트롤
        }

        // 좌우 컨트롤 횟수 -> 최적의 해를 찾아야 함
        if value != 65 {
            var next = current + 1
            while next < name.count && name[next].asciiValue == 65 { // 연속해서 A가 나오면
                next += 1
            }
            move = 2 * current + name.count - next
            minMove = min(move,minMove)
        }
        current+=1
    }

    return ans + minMove
}

print(solution("JAZ"))

 

여기서 value!= 65 부분을 보면 A가 아닌 경우에 내 다음의 문자가 A인 경우 어떻게 처리할 것인지에 대한 부분이다.

next를 통해서 내 문자열 기준으로 A가 연속해서 몇개가 나오는지를 판단한다.

다음으로는 move = 2 * current + name.count - next 이 부분이다.

이건 어떤 말이냐면

코드에 대한 설명

우리는 기본적으로 우측방향으로 계속 진행하였을 때의 값이 최솟값이라고 가정한다.

그런데, 만약 A를 만나서 방향을 바꾸는게 이득이 되는 경우 바꿔야 하겠지? 그래서 내가 A를 만난idx 기준으로 연속된 A의 문자열의 끝까지 길이를 잰후, 현재 위치에서 방향을 돌아 반대쪽 연속된 A스트림을 만나는 곳까지 어떤게 더 소요 비용이 적은지 확인하는 코드이다.

 

그렇다면 왜 current * 2를 하는 것일까?

식에 대한 더 자세한 설명

current는 현재 오른쪽을 진행한 후에 다시 되돌아 가야하는 기회비용을 포함하여 왔다갔다 하니까 그렇게 된다.

그리고 name.count - next는 A문자열을 빼고 순회하는 카운팅 수이다