Home 프로그래머스 - 조이스틱
Post
Cancel

프로그래머스 - 조이스틱

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

Link

문제

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

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

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

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

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

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

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

입출력 예

namereturn
“JEROEN”56
“JAN”23

풀이

Level 2이지만 참으로 까다로운 문제였다.

결국 자력으로 풀지 못해 아래 링크를 참고하여 문제를 해결하였다.

  • https://whatryando.tistory.com/142

우선 원하는 알파벳으로 조작하는 것부터 생각해보자.

모든 자리의 알파벳은 ‘A’부터 시작한다.

‘A’에서 ‘B’를 만드려면 ▲버튼을 한번 누르면 된다.

‘A’에서 ‘Z’를 만드려면 ▼버튼을 한번 누르면 된다.

즉 ‘A’에서 순서대로 올라가 원하는 알파벳을 만드는 방법이 있고, 거꾸로 올라가 만드는 방법이 있다.

두 방법중 더 적은 조작이 필요한 방법으로 선택하면 된다.

이제 문제는 커서를 이동하는 일이다.

알파벳 ‘A’는 변경이 필요가 없기 때문에 ‘A’의 위치에 따라 단순히 커서를 순서대로 움직이는 것이 최소 조작횟수가 될 수도 있고 순서대로 갔다가 거꾸로 가는 것이 최소 조작횟수가 될 수도 있다.

‘A’가 없다면 순서대로 가던 거꾸로 가던 조작횟수는 같다.

따라서 각 위치에 따른 조작횟수를 비교하여 최소 조작횟수를 구해야만한다.

예를들면 ‘BAACD’가 있을 때, ‘B’의 위치에서 ‘AACD’ 순서대로 처리하는 것과, ‘B’를 처리하고 거꾸로 거슬러가 ‘DC’ 순서로 처리하는 것의 조작횟수를 비교해야한다.

전자는 이동횟수만 따졌을 때 4번의 조작이 필요하고, 후자는 2번의 조작이 필요하다.

여기서 끝나면 안되고 ‘C’의 위치에서도 ‘DB’의 순서로 처리하는 것과 거꾸로가서 ‘BD’의 순서로 처리하는 것의 조작횟수를 최소 조작횟수와 비교해야한다.

(해당 자리까지 온다음 그대로 순서대로 처리할 경우의 이동횟수, 뒤돌아 거슬러 올라갈때의 이동횟수)

‘C’의 위치에서 ‘DB’의 순서로 처리하는 것은 일단 ‘B’에서 ‘C’로 이동하는 것 3번 + ‘D’로 이동 1번 = 총 4번이다.

‘C’의 위치에서 ‘BD’ 순서로 처리하는 것은 ‘D’로 돌아가는데 4번의 이동 = 총 4번이다.

모든 자리에서의 비교가 이루어지면 그때의 알파벳 변환을 위한 조작횟수와 이동횟수를 더해서 반환하면 된다.

이를 코드로 작성하면 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def solution(name):
    # https://whatryando.tistory.com/142
    answer = 0
    # 순서대로 vs 거꾸로 중 더 적은 조작의 숫자로 변경
    num_list = [min(abs(ord('A') - ord(c)), 26-abs(ord('A') - ord(c))) for c in name]
	
    answer += sum(num_list)
    min_move = len(name) - 1
    
    for i, c in enumerate(name):
        next_i = i+1
        while next_i < len(name) and name[next_i] == 'A':
            next_i += 1

        min_move = min(min_move, 2*i+ len(name)-next_i, 2*(len(name)-next_i)+i)
    
    return answer+min_move
This post is licensed under CC BY 4.0 by the author.

LeetCode - 128. Longest Consecutive Sequence

프로그래머스 - 큰 수 만들기