본문 바로가기
[Python] Programmers/Level2

[프로그래머스/Level2] 조이스틱

by 파크영 2021. 7. 12.

문제 설명

조이스틱으로 알파벳 이름을 완성하세요. 맨 처음엔 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

나의 풀이

[Python(파이썬)]

def solution(name):
    answercnt, nowindex, indexcnt, tf = 0, 0, 0, True
    name = list(name)
    while tf:
        if name.count('A') == len(name):
            tf = False
        else:
            # 상하 이동하는 파트
            if name[nowindex] != 'A':
                answercnt += min((ord(name[nowindex]) - 65), 91 - ord(name[nowindex]))
                name[nowindex] = 'A'
                continue
            # 좌우 이동하는 파트
            else:
                l, r = 1, 1
                # 왼쪽
                while name[nowindex - l] == 'A':
                    l += 1
                # 오른쪽
                while name[nowindex + r] == 'A':
                    r += 1

                if l < r:
                        answercnt += l
                        nowindex += -l
                else:
                        answercnt += r
                        nowindex += r

    return answercnt

 

학습한 내용

풀이 과정
1. ▲, ▼ 둘 중에 어느 것이 더 빠른가?
2. ◀, ▶ 둘 중에 어는 것이 더 빠른가?
3. 1, 2번을 같이 생각해야하는가?

 

3번 부터 생각해보자면 1, 2번을 같이 생각해야하는가?

-> 좌우 커서와 위아래 알파벳 이동은 연관성이 없어 보이므로 독립적으로 계산

 

1. ▲, ▼ 둘 중에 어느 것이 더 빠른가? -> 알파벳 찾기

 

A -> 움직이지 않기

B-Z 는 A에서 조작횟수가 최솟값인 것을 찾기

# 'A'가 아닌 경우 
# 위아래의 경우 두가지를 각각 구한 후 최솟값 구하기 
if name[nowindex] != 'A':
    answercnt += min((ord(name[nowindex]) - 65), 91 - ord(name[nowindex]))
    name[nowindex] = 'A'
    continue

 

2. ◀, ▶ 둘 중에 어느 것이 더 빠른가? -> 좌우 이동하기

 

현재 위치에서 'A'가 아닌 다른 문자가 있는 곳으로 커서 이동

좌우 중에 어느 것이 더 적게 움직일지 구하기 (인덱스 0번 부터가 아닌 현재 위치에서 라는 점 유의)

 

테스트 4, 7번 오류 코드

def solution(name):
    answercnt, nowindex, indexcnt, tf = 0, 0, 0, True
    name = list(name)
    num = [i for i, x in enumerate(name) if x != 'A']
    while tf:
        if name.count('A') == len(name):
            tf = False
        else:
            # 상하 이동하는 파트
            if name[nowindex] != 'A':
                answercnt += min((ord(name[nowindex]) - 65), 91 - ord(name[nowindex]))
                name[nowindex] = 'A'
                del num[num.index(nowindex)]
                continue
            # 좌우 이동하는 파트
            else:
                if not num:
                    return answercnt
                else:
                    if abs(num[0] - nowindex) <= abs(len(name) + nowindex - num[-1]):
                        answercnt += abs(num[0] - nowindex)
                        nowindex = num[0]
                    else:
                        answercnt += abs(len(name) + nowindex - num[-1])
                        nowindex = num[-1]

    return answercnt

 

인덱스 0번 부터가 아닌 현재 위치에서 라는 점을 생각했으나 생각대로 문제가 잘 풀리지 않아서 다시 처음부터 시작했다. 

def solution(name):
    answercnt, nowindex, indexcnt, tf = 0, 0, 0, True
    name = list(name)
    while tf:
    	l, r = 1, 1
        if name.count('A') == len(name):
            tf = False
        else:
            # 상하 이동하는 파트
            if name[nowindex] != 'A':
                answercnt += min((ord(name[nowindex]) - 65), 91 - ord(name[nowindex]))
                name[nowindex] = 'A'
                continue
            # 좌우 이동하는 파트
            else:
                # 왼쪽
                while name[nowindex - l] == 'A':
                    l += 1
                # 오른쪽
                while name[nowindex + r] == 'A':
                    r += 1

                if l < r:
                        answercnt += l
                        nowindex += -l
                else:
                        answercnt += r
                        nowindex += r

    return answercnt

 

  • ord(문자) : 문자를 아스키 코드로 변환
  • chr(숫자) : 아스키 코드를 문자로 변환
 

[Python] 문자, 아스키코드 변환

ord(문자) : 문자 -> 아스키코드 >>> ord('A') 65 >>> ord(' ') 32 >>> ord('a') 97 >>> ord('*') 42 chr(숫자) : 아스키코드 -> 문자 >>> chr(65) 'A' >>> chr(97) 'a' >>> chr(32) ' ' >>> chr(42) '*'

young-library.tistory.com

 

 

  • 리스트에서 찾고자 하는 item의 index를 모두 찾는 방법 - filter(), enumerate()

학습 한 후 아래 링크와 같이 정리 해 두었다. 

 

[Python] filter(), enumerate() - 찾고자하는 item의 index 모두 찾기

index() 찾고자 하는 item의 index 반환 리스트에서 index()를 사용하면 찾고자하는 item의 index가 가장 작은 한개만 반환한다. >>> test = 'ABAABB' >>> test = list(test) >>> test.index('B') 1 찾고자 하는 i..

young-library.tistory.com

 


문제 출처

 

코딩테스트 연습 - 조이스틱

조이스틱으로 알파벳 이름을 완성하세요. 맨 처음엔 A로만 이루어져 있습니다. ex) 완성해야 하는 이름이 세 글자면 AAA, 네 글자면 AAAA 조이스틱을 각 방향으로 움직이면 아래와 같습니다. ▲ - 다

programmers.co.kr

 

댓글