코딩테스트/프로그래머스

[프로그래머스 Level2] 조이스틱 - 파이썬(Python)

yejin72 2023. 1. 10. 23:15
728x90

https://school.programmers.co.kr/learn/courses/30/lessons/42860

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제 설명

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

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

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

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

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

만들고자 하는 이름 name이 매개변수로 주어질 때, 이름에 대해 조이스틱 조작 횟수의 최솟값을 return 하도록 solution 함수를 만드세요.

 

 

 


이 문제는 우선 거시적으로 설명하면 (초기화 상태의 'A'에서 다른 알파벳으로 변화하는 최소 조작 횟수) + (커서의 최소 조작 횟수)의 값을 반환해주어야 하는 문제이다. 이때, 커서의 최소 조작 횟수를 구하는 과정이 조금 신경쓸게 많다.

 

 

name에 'A' 문자가 존재하지 않는다면 커서를 단순하게 오른쪽으로 계속해서 옮겼을 때의 조작 횟수만을 구해 반환한 것이 최소 조작 횟수이다. 그러나, 'A' 문자가 존재한다면 처음부터 'A'문자들로 초기화되어있었기 때문에 그냥 지나치거나 무시해도 상관없다.

 

name = "XAAABA"의 케이스를 생각해 보자.

>>>>> : 5번 이동
<<>> : 4번 이동
<< : 2번 이동
  • A의 존재 여부를 따지지 않고 가장 왼쪽부터 하나씩 커서를 오른쪽으로 이동하면 5번 이동된다.
  • X(AAA)BA 로 나누어 생각했을 때, 처음에 커서를 왼쪽으로 이동해서 BA를 방문하고, 다시 되돌아와서 X를 방문하면 4번 이동된다.
  • X(AAA)BA 로 나누어 생각했을 때, X로 만들고 커서를 왼쪽으로 이동해서 BA를 방문해면 총 2번 이동된다.

이처럼, 'A' 문자들의 묶음의 왼쪽 문자열을 먼저 방문 후 오른쪽 문자열을 방문하는 경우의 조작 횟수오른쪽 문자열을 방문 후 왼쪽 문자열을 방문하는 경우의 조작 횟수는 좌우 문자열의 길이에 따라 다르기 때문에 2가지 케이스 모두의 방문 횟수들을 확인했다.

 

 

 

'A'문자들의 묶음은 여러 개 있을 수 있다.

아래의 코드를 이용해서 미리 'A'문자들의 묶음들의 각 시작 인덱스와 마지막 인덱스들을 구했다.

i = 0
sections = []
while i < len(name):
    if name[i] == 'A':
        arr = [i, i - 1]
        while i < len(name) and name[i] == 'A':
            arr[1] += 1
            i += 1
        sections.append(arr)
    else:
        i += 1

 

 

초기화 상태인 'A'에서 'A'~'Z' 사이의 알파벳으로 변할 때의 최소 카운트 횟수는 다음의 코드로 구한다.

min(ord('Z') - ord(name[i]) + 1, ord(name[i]) - ord('A'))

 

 

 

 

 

<< 최종 코드 >>

def solution(name):
    answer = 0
    for c in name:
        answer += min(ord('Z') - ord(c) + 1, ord(c) - ord('A'))
    answer += len(name) - 1
    if not 'A' in name:
        return answer

    i = 0
    sections = []
    while i < len(name):
        if name[i] == 'A':
            arr = [i, i - 1]
            while i < len(name) and name[i] == 'A':
                arr[1] += 1
                i += 1
            sections.append(arr)
        else:
            i += 1
    
    for s, e in sections:
        count = 0
        for i in range(s):
            count += min(ord('Z') - ord(name[i]) + 1, ord(name[i]) - ord('A'))
        for i in range(e+1, len(name)):
            count += min(ord('Z') - ord(name[i]) + 1, ord(name[i]) - ord('A'))
        if s == 0:
            answer = min(answer, count + len(name[e+1:]))
        elif e == len(name) - 1:
            answer = min(answer, count + len(name[:s]) - 1)
        else:
            answer = min(answer, count + (len(name[:s])-1) * 2 + len(name[e+1:]))
            answer = min(answer, count + 1 + (len(name[e+1:])-1) * 2 + 1 + len(name[:s]) - 1 )
    return answer

 

728x90