[프로그래머스-레벨2]조이스틱 - python

iamjinseo·2022년 9월 27일
0

문제풀이-Python

목록 보기
107/134

https://school.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 이하입니다.

입출력 예

namereturn
"JEROEN"56
"JAN"23

풀이

import string
def solution(name):
    min_move = len(name) -1 
    cnt = 0
    
    while name[min_move] == 'A' and min_move > 0 : #마지막이 A일 때
        min_move -= 1
        
    if min_move < 0 : return 0 #전부 A면 0리턴

    for i, l in enumerate(name):
        cnt += min(ord(l)-ord('A'), ord('Z')-ord(l)+1) # 상하좌우 적게 이동
        
        # A탐색
        next = i + 1
        while next < len(name) and name[next] == 'A':
            next += 1 #연속되는 A중에서, 마지막으로 A인 곳
        
        min_move = min_move = min([min_move, 2 *i + len(name) - next, i + 2 * (len(name) -next)])
    return min_move+cnt          

BAAABBABABAB테스트케이스 추가해보고 나혼자 열심히 코딩하다가 결국 아이디어가 떠오르지 않아 구글링을...^^ (참고 - https://velog.io/@jqdjhy/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%A1%B0%EC%9D%B4%EC%8A%A4%ED%8B%B1-Greedy)

min_move = len(name) -1 
    cnt = 0

초기에 최소이동횟수를 문자열의 개수로 둔다.

while name[min_move] == 'A' and min_move > 0 : #마지막이 A일 때
        min_move -= 
if min_move < 0 : return 0 #전부 A면 0리턴

마지막 글자가 A일 때 최소이동횟수를 줄인다.
최소이동횟수가 0이하가 되면 0을 리턴한다.

for i, l in enumerate(name):
        cnt += min(ord(l)-ord('A'), ord('Z')-ord(l)+1) # 상하좌우 적게 이동

알파벳을 효율적이게 바꾸는 알고리즘이다. 예를 들어 알파벳이 B이면 1과 25중에서 더 작은 값을 비교한다.

# A탐색
next = i + 1
while next < len(name) and name[next] == 'A':
	next += 1 #연속되는 A중에서, 마지막으로 A인 곳
min_move = min_move = min([min_move, 2 *i + len(name) - next, i + 2 * (len(name) -next)])

A들 중에서 마지막으로 A인 곳을 알아낸다.

왼쪽에서 오른쪽으로 탐색 후 A를 만나면 왼쪽편으로 되돌아가면서 맨 오른쪽부터 재탐색하는 게 짧은지
아니면 시작부터 오른쪽에서 왼쪽으로 탐색한 후 A를 만나면 오른쪽으로 되돌아가 맨 왼쪽부터 재탐색하는 게 짧은지
그것도 아니면 min_move가 가장 짧은지 선택한다.

결과


남의 코드

다른사람의 풀이 찾아봤는데 죄다 반박 댓글이 있어서 가져오지 못했다......

후기

너무 어렵다......내 수준에 안맞는 문제를 만나버렸어

레벨1이랑 2랑 수준차이 너무 나는데??? 다시 백준 실버부터 풀어야되나

profile
일단 뭐라도 해보는 중

0개의 댓글