개발/Swift

[Swift] 조이스틱 코딩테스트 프로그래머스

덤벨로퍼 2022. 2. 13. 14:12

 

 

문자 변환 카운팅을 위해서 아스키 코드를 활용한다.

 

위의 아스크코드 표를 참고하면 하늘색부분을 보면 된다.

A는 65 → Z 는 90이다.

조이스틱을 위로 / 아래로 변경해서 원하는 문자를 찾을건데 

위로가는 방법 , 아래로 가는 방법 두개를 비교해 최솟값을 구하면된다.

 

찾으려는 문자의 아스키코드 번호를 알아낸 다음

위로가는 방법은 = 아스키코드번호 - 65 (ex>A 인경우 0)

아래는 = 91 - 아스키코드번호 이렇게 계산하면 쉽다. (Z인경우 1)

for i in range{
        if name[i] != "A"{
            let up = name[i].asciiValue! - 65
            let down = 91 - name[i].asciiValue!
            changeCount += Int(min(up, down))
        }
    }

 

더 어려웠던 문제는 이동횟수였다.

해답에서는 이렇게 되어있었다.

var minMove = name.count - 1
   
    for i in 0..<name.count {
       if name[i] != "A" {
           var next = i + 1
           while next<name.count && name[next] == "A" {
               next += 1          
					 }
           let move = 2 *  i + name.count - next
           minMove = min(move, minMove)
       }
   }

봐도 모르겠어서 하나하나 대입해가면서 이해해본 결과 이 코드의 해답은 이러하다.''

BAAABB //2번쨰 A 앞에서 돌아가기
BABAAB  //2번쨰 A 앞에서 돌아가기  
BBAAAB //3번쨰 A 앞에서 돌아가기
AABABB // 오른쪽으로 세기
ABAABB // 3번쨰 A에서 돌아가기

 

오른쪽으로 순차적으로 움직이기 방법 + 첫번째 A앞에서 돌아가는 방법만 생각했지만

몇번째 A에서 돌아갈지는 문자에 따라 달라진다.

BABAAB 는 맨처음 나오는 A 에서 돌아가지만

ABAABB 는 두번쨰 나오는 A에서 반대로 돌아가야 한다.

 

결국 이렇게 나뉜다.

오른쪽으로 순차적으로 움직이기

첫번쨰 A 앞에서 돌아가기

두번쨰 A 앞에서 돌아가기

세번쟤.... 네번째...

결국 다 세보고 비교해야한다.

 

반복문을 돌린후 다음값에 A가 나오면 최솟값을 계산해낸후 기존 최솟값과 비교하여

계속 최소값을 최신화하면서 풀이 해야한다.

위 반복문에서 i 는 A가 발견된 직전 index 이며

next 는 A의 위치이다. A가 연달아 나올수 있으므로 while문을 돌려 next를 +1 하면서

연달아 나온 마지막 A값을 next에 대입했다.

while next<name.count && name[next] == "A" {
           next += 1 
       }

되돌아간 무빙 횟수 = A직전 index * 2(오른쪽으로 갔다가 되돌아 왔으므로) + A 이후 A아닌 문자 갯수

이렇게 계산한후 직전 최소값과 지금 최소값을 비교해 값을 도출해 냈다.

let move = 2 *  i + name.count - next
minMove = min(move, minMove)

 

전체 코드

 

import Foundation
func solution(_ name:String) -> Int {
    var ans = 0
    let name = name.map({$0})
    for i in 0..<name.count {
        if name[i] != "A" {
            let up = name[i].asciiValue! - 65
            let down = 91 - name[i].asciiValue!
            ans += Int((up<down) ? up : down)
        }
    }

    var minMove = name.count-1
    for i in 0..<name.count {
        if name[i] != "A" {
            var next = i + 1
            while next<name.count && name[next] == "A" {
                next += 1
            }
            let move = 2 *  i + name.count - next
            minMove = min(move, minMove)
        }
    }
    return ans + minMove
}