[프로그래머스] 조이스틱 - 파이썬

728x90

문제 설명

조이스틱으로 알파벳 이름을 완성하세요. 맨 처음엔 A로만 이루어져 있습니다.
ex) 완성해야 하는 이름이 세 글자면 AAA, 네 글자면 AAAA

조이스틱을 각 방향으로 움직이면 아래와 같습니다.

▲ - 다음 알파벳
▼ - 이전 알파벳 (A에서 아래쪽으로 이동하면 Z로)
◀ - 커서를 왼쪽으로 이동 (첫 번째 위치에서 왼쪽으로 이동하면 마지막 문자에 커서)
▶ - 커서를 오른쪽으로 이동 (마지막 위치에서 오른쪽으로 이동하면 첫 번째 문자에 커서)


예를 들어 아래의 방법으로 "JAZ"를 만들 수 있습니다.

- 첫 번째 위치에서 조이스틱을 위로 9번 조작하여 J를 완성합니다.
- 조이스틱을 왼쪽으로 1번 조작하여 커서를 마지막 문자 위치로 이동시킵니다.
- 마지막 위치에서 조이스틱을 아래로 1번 조작하여 Z를 완성합니다.
따라서 11번 이동시켜 "JAZ"를 만들 수 있고, 이때가 최소 이동입니다.
만들고자 하는 이름 name이 매개변수로 주어질 때, 

이름에 대해 조이스틱 조작 횟수의 최솟값을 return 하도록 solution 함수를 만드세요.

제한 사항

name은 알파벳 대문자로만 이루어져 있습니다.
name의 길이는 1 이상 20 이하입니다.

 

입출력 예

name return
"JEROEN" 56
"JAN" 23

 

 

정답해설

본 문제는 그리디지만, 어느정도 구현 문제처럼 보였다.

 

하지만, 문제를 읽다가 보니, 이 문제는 단어의 유니코드 값으로 해결하면 쉽겠다는 생각이 들었다.

 

이번 문제에서 고려해야 될 부분은 크게 아래 두가지다.

 

1. 현재 단어에서 정답 단어까지 변조해야되는 횟수

2. 다음 단어로 이동하는 횟수

 

1번 같은 경우는 매우 간단하다. 그저 유니코드 수의 차이를 비교하면 된다.

여기서 비교하고자 하는 단어와 A까지의 거리를 계산하고,

Z까지의 거리를 계산해서 위와 아래의 조작 거리의 최소값을 구해서 정해주면 된다.

 

문제는 2번 사항이다.

 

이동하는 횟수를 계산하는 것이 생각보다 어려웠는데,

앞으로 이동하는 것과 뒤로 이동하는 것 중에 뭐가 더 빠른지 비교하기 위해선,

다음 단어가 정답 단어와 같은지 알아내야 한다.

 

이렇게 알아낼 수 있게 된다면, 앞과 뒤로의 이동 중에서 더 적은 이동횟수를 갖는 방식으로 골라주면 된다.

 

나는 이번 문제를 해결하기 위해서 다음으로 이동하는 인덱스의 이동 횟수를 계산했다.

곧이어 뒤로 가는 것과 앞으로 가는 것의 최소값을 찾아서 사용하면 된다.

 

설명이 조금 부족했는데, 아래의 코드를 보면 이해할 수 있을 것이다.

 

정답코드

def solution(name):
    answer = 0
    for char in name:
        answer += min(ord(char) - ord('A'), ord('Z') - ord(char) + 1)
    
    length = len(name)
    min_moves = length - 1
    
    for i in range(length):
        next_index = i + 1
        while next_index < length and name[next_index] == 'A':
            next_index += 1
        
        min_moves = min(min_moves, i + length - next_index + min(i, length - next_index))
    
    answer += min_moves
    return answer
728x90