[PG] 조이스틱

이나영·2022년 3월 20일
0
post-thumbnail

"조이스틱" - Lv.2

🎲문제설명

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

📓문제 이해 및 풀이계획

✏️nameA인 곳은 회전하지 않아도 된다.

✏️마지막 검사하는 A...A는 이동하지 않아도 된다. (꼭 모든 위치를 거쳐서 확인하지 않아도 됨, 이동 횟수 x)

✏️0번째 위치에서 오른쪽으로 가거나①, 왼쪽(마지막위치로 역방향)②으로 이동할 수 있다.

문제를 풀 때, 나는 오른쪽으로 쭉 가거나 왼쪽으로 쭉 가는 경우만 생각했는데, 중간에 A...A인 곳이 있다면 갔던 길을 되돌아서 중간의 A...A인 곳을 거치지 않는 방법이 있었다...! 글로 적으려니까 잘 설명이 안되는 것 같은데 (ㅠㅠ)
프로그래머스 질문하기에 보니, "AABAAAAABBB" 경우 0->1->2->1->0->10->9->8 로 이동 시 횟수가 가장 적게나왔다.

⭐️->, <-, <- 오른쪽으로 이동, 왔던 길 되돌아가서, 역방향으로 가는 방법③

⭐️<-, ->, -> 역방향으로 이동, 왔던 길 되돌아가서, 정방향으로 가는 방법④



✍🏻내 코드2 + 정답코드

class Solution {
    public int solution(String name) {
        // 돌리는 횟수
		int rotate = 0;
		for(int i=0; i<name.length(); i++) {
			if(name.charAt(i) != 'A') {
				rotate += Math.min((((int) name.charAt(i)) - 65), (91 - (int) name.charAt(i)));
			}
		}
		
		// 정방향
		int idx_f = 0;
		for(int i=name.length()-1; i>=0; i--) {
			if(name.charAt(i) != 'A') {
				idx_f = i;
				break;
			}
		}
		
		int min = Integer.MAX_VALUE;
		int move = 0;
		for(int i=0; i<idx_f; i++) {
			move += 1;
		}
		min = Math.min(min, move);
		
		// 역방향
		int idx_b = 0;
		for(int i=1; i<name.length(); i++) {
			if(name.charAt(i) != 'A') {
				idx_b = i;
				break;
			}
		}
		move = 0;
		for(int i=name.length()-1; i>=idx_b; i--) {
			move += 1;
		}
		min = Math.min(min, move);
		
		// 다시 되돌아가는 경우 (중간에 존재하는 A를 모두 검사)
		int start, end;
		for(int i=0; i<name.length(); i++) {
			if(name.charAt(i) == 'A') {
				start = i;
				for(int j=start+1; j<name.length(); j++) {
					if(name.charAt(j) != 'A') {
						end = j-1;
						move = checkA(start, end, name.length()-1);
						break;
					}
				}
			}
			min = Math.min(min, move);
		}
		
        return rotate+min;
    }
    
    	public static int checkA(int start, int end, int l) {
		int move = 0;
		if(start == 0) start = 1;
		// 정방향 후 역방향
		move = (start-1)*2 + (l-end);
		
		// 역방향 후 정방향
		move = Math.min(move, (l-end)*2 + start-1);
		return move;
	}
}

💡케이스를 나누기 전에 막연하게 생각만 했을 때는 뭔가 생각할 경우의 수가 엄청 많고 복잡하게 느껴졌는데, 글로 경우의 수를 하나하나 따져보면서 적어보니까 어렵지 않았다. 머리가 복잡할 땐, 글로 찬찬히 적어보는 습관을 들이자 !

profile
소통하는 백엔드 개발자로 성장하기

0개의 댓글

관련 채용 정보