Min:D's Devlog

[프로그래머스][그리디][C++] 조이스틱 본문

알고리즘/프로그래머스

[프로그래머스][그리디][C++] 조이스틱

Min:D 2020. 7. 4. 01:25

문제

프로그래머스 그리디 - 조이스틱

 

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

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

programmers.co.kr

문제 설명

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

 


문제 풀이

접근 방식

조이스틱을 움직이는 횟수는 이름을 구성하는 알파벳과 그 위치에 의해 결정된다.

 

1) 알파벳

 

A ~ N은 ▲ 방향으로 이동(0 ~ 13), Z ~ M은 ▼ 방향으로 이동(1 ~ 12)시켜야 최소 횟수로 변경할 수 있다.

총 이동 횟수 변수인 answer에 이 모든 횟수를 더한다.

 

2) 위치

 

초기에는 모든 알파벳이 A로 설정되어 있다. (Ex) AAA, AAAAAA)

그래서 바꿔야 할 이름의 알파벳 중 A인 경우에는 바꿀 필요가 없다.

따라서 조이 스틱을 최소 횟수로 이동시키기 위해 고려해봐야 할 이동 방향은 4가지이다.

 

  1. ▶ (): 뒷부분이 A인 경우 최소

    Ex) BBBBAA이면 오른쪽으로 3번만 이동하면 됨

  2. ◀ :앞부분이 A인 경우 최소

    Ex) AAAAABBB이면 왼쪽으로 3번만 이동하면 됨

  3. ▶◀ : 중간에 A가 많은 경우 중 앞부분에 A가 아닌 알파벳이 더 적은 경우

    Ex) BBBAAAAAAAAABBBBB이면 오른쪽으로 2번, 왼쪽으로 2 + 5번. 즉, 2 * 2 + 5 = 9번만 이동하면 됨

  4. ◀▶ : 중간에 A가 많은 경우 중 뒷부분에 A가 아닌 알파벳이 더 적은 경우

    Ex) BBBBBBBAAAAAAAAABBB이면 왼쪽으로 3번, 오른쪽으로 3 + 6번. 즉, 3 * 2 + 6 = 12번만 이동하면 됨

이 4가지 경우의 이동 횟수를 세기 위해 front, back, half_front, half_back 변수를 사용하였다.

그리고 front, back, half_front * 2 + half_back, half_back * 2 + half_front 중 최솟값을 answer에 더해주었다.

 


풀이 코드 - C++

#include <algorithm>

using namespace std;

int solution(string name) {
	int len = name.size();
	int mid = len / 2;
    
	int front = 0;
	int back = 0;
	int half_front = 0;
	int half_back = 0;
    
	int answer = name[0] - 'A';
	if(answer > 13)
		answer = 'Z' - name[0] + 1 ;
    
	for (int i = 1; i < len; i++) {
		if (name[i] <= 'N')
			answer += name[i] - 'A';
		else
			answer += 'Z' - name[i] + 1;
        
		if (name[i] != 'A') {
			front = i;
			if (i <= mid)
				half_front = i;
		}
        
		if (name[len - i] != 'A') {
			back = i;
			if (len - i > mid)
				half_back = i;
		}
	}
    
	answer += min(min(front, back), min(half_back * 2 + half_front, half_front * 2 + half_back));
	return answer;
}

실행 결과

Comments