[프로그래머스] 조이스틱 / Python
문제주소 :programmers.co.kr/learn/courses/30/lessons/42860
<문제 설명>
문제 설명
조이스틱으로 알파벳 이름을 완성하세요. 맨 처음엔 A로만 이루어져 있습니다.
ex) 완성해야 하는 이름이 세 글자면 AAA, 네 글자면 AAAA
조이스틱을 각 방향으로 움직이면 아래와 같습니다.
▲ - 다음 알파벳 ▼ - 이전 알파벳 (A에서 아래쪽으로 이동하면 Z로) ◀ - 커서를 왼쪽으로 이동 (첫 번째 위치에서 왼쪽으로 이동하면 마지막 문자에 커서) ▶ - 커서를 오른쪽으로 이동
예를 들어 아래의 방법으로 JAZ를 만들 수 있습니다.
- 첫 번째 위치에서 조이스틱을 위로 9번 조작하여 J를 완성합니다. - 조이스틱을 왼쪽으로 1번 조작하여 커서를 마지막 문자 위치로 이동시킵니다. - 마지막 위치에서 조이스틱을 아래로 1번 조작하여 Z를 완성합니다. 따라서 11번 이동시켜 "JAZ"를 만들 수 있고, 이때가 최소 이동입니다.
만들고자 하는 이름 name이 매개변수로 주어질 때, 이름에 대해 조이스틱 조작 횟수의 최솟값을 return 하도록 solution 함수를 만드세요.
제한 사항
- name은 알파벳 대문자로만 이루어져 있습니다.
- name의 길이는 1 이상 20 이하입니다.
입출력 예
name returnJEROEN | 56 |
JAN | 23 |
<풀이법>
▒ 한줄 개념: 탐욕법? ▒
이 문제는 탐욕법에 분류되어 있습니다. 하지만 탐욕법이라고 하기엔 애매한 문제입니다.
탐욕법으로 풀 수는 있지만, 탐욕법으로 풀 경우 최적해가 나오지 않는 경우가 존재합니다.
완전한 최적해를 풀기 위해서는 조건이 많이 필요하므로, DFS나 BFS 등의 완전탐색 기법이 요구될 것 같습니다.
저 같은 경우는 완전한 최적해를 탐욕적으로 풀려고 하다 시간을 많이 낭비했습니다.
일단 탐욕법으로 푸는 방식은 다음과 같습니다.
- 모든 target 문자에 대해 A로부터의 거리와 Z로부터의 거리 중 작은 값 저장( target문자 A일 경우 변환 필요없으므로 값 0 넣어줌)
- left, right 각각 1씩 늘려가며 target 문자 A가 아닌 문자에 먼저 도달하는 경우 찾기.
- left, right 중 더 짧은 거리의 위치로 이동하여 반복
<코드(Python)>
def solution(name): # 65~90(A~Z)
moves = [min(ord(s) - ord('A'), ord('Z') - ord(s) + 1) for s in name]
pos = 0
answer = 0
while True:
answer += moves[pos]
moves[pos] = 0
if sum(moves) == 0: break
left = 1
right = 1
while moves[pos - left] == 0:
left += 1
while moves[pos + right] == 0:
right += 1
if left >= right:
pos += right
answer += right
else:
pos -= left
answer += left
return answer
더 많은 코드 보기(GitHub) : github.com/dwkim-97/CodingTest