[Programmers] - 키패드 누르기

오동훈·2021년 4월 24일
0

Programmers

목록 보기
28/64
post-thumbnail

1. Problem 📃

https://programmers.co.kr/learn/courses/30/lessons/67256

다음 문제는, 키패드가 있을때 문제의 조건에 맞춰 먼저 입력되는 손가락을 체킹해 반환하는 문제입니다.

2. Logic 👨‍🏫

  1. 문제의 조건처럼 1, 4, 7이 입력될때는 왼손이 입력되게끔 하고 값을 저장했습니다.
  2. 문제의 조건처럼 3, 6, 9가 입력될때는 오른손이 입력되게끔 하고 값을 저장했습니다.
  3. 이들을 제외한 2, 5, 8, 0이 나올때 L과 R을 구하는것이 관건인데, 이 부분은 상하좌우로 이동할때 각각 상, 하(-3, +3), 좌,우(-1, +1)의 변화가 있는것을 확인할 수 있습니다.
  4. 마지막 손의 위치와 2, 5, 8, 0간의 절댓값을 구하고 이를 3으로 나눈 몫과 나머지를 더하면 키패드 상의 거리를 구할 수 있습니다.

3. Code 💻

1. fail code,, 발상이 잘못됨😥

def solution(numbers, hand):
    answer = ''
    l_hand = 10
    r_hand = 12
    for i, v  in enumerate(numbers):
        tmp = 0
        if v in [1, 4, 7]:
            answer += 'L'
            l_hand = v
        elif v in [3, 6, 9]:
            answer += 'R'
            r_hand = v
        else:
            if v == 0:
                v = 11
            if abs(l_hand - v) == abs(r_hand - v): # 일직선인 경우
                if hand == 'right':
                    answer += 'R'
                    r_hand = v
                else:
                    answer += 'L'
                    l_hand = v
            else:
                # or (abs(r_hand - v) % 3 == 0 and abs(l_hand - v) == 1) or 
                # (abs(r_hand - v) % 3 == 0 and abs(l_hand - v) == 2) or 
                # (abs(l_hand - v) % 3 == 0 and abs(r_hand - v) == 2):
                if (abs(l_hand - v) == 1 and abs(r_hand - v) == 3) or (abs(l_hand - v) == 3 and abs(r_hand - v) == 1): # 손이 우선
                    if hand == 'right':
                        answer += 'R'
                        r_hand = v
                    else:
                        answer += 'L'
                        l_hand = v
                elif (abs(l_hand - v) == 4 and abs(r_hand - v) == 6) or (abs(l_hand - v) == 2 and abs(r_hand - v) == 6) or (abs(l_hand - v) == 6 and abs(r_hand - v) == 2) or (abs(l_hand - v) == 6 and abs(r_hand - v) == 4):
                    if hand == 'right': # 손이 우선
                        answer += 'R'
                        r_hand = v
                    else:
                        answer += 'L'
                        l_hand = v
                elif (abs(l_hand - v) == 1 and abs(r_hand - v) == 6) or (abs(l_hand - v) == 6 and abs(r_hand - v) == 1):
                    if abs(l_hand - v) > abs(r_hand - v): # 값이 작은게 대입
                        answer += 'R'
                        r_hand = v
                    elif abs(l_hand - v) < abs(r_hand - v):
                        answer += 'L'
                        l_hand = v
                elif (abs(l_hand - v) == 4 and abs(r_hand - v) == 3) or (abs(l_hand - v) == 2 and abs(r_hand - v) == 3):
                        answer += 'R'
                        r_hand = v
                elif (abs(l_hand - v) == 3 and abs(r_hand - v) == 2) or (abs(l_hand - v) == 3 and abs(r_hand - v) == 4):
                        answer += 'L'
                        l_hand = v
                elif (abs(l_hand - v) == 3 and abs(r_hand - v) == 6) or (abs(l_hand - v) == 6 and abs(r_hand - v) == 3):
                        if abs(l_hand - v) > abs(r_hand - v):
                            answer += 'R'
                            r_hand = v
                        elif abs(l_hand - v) < abs(r_hand - v):
                            answer += 'L'
                            l_hand = v
                else:
                    if hand == 'right':
                        tmp = l_hand + 2
                        if abs(tmp - v) > abs(r_hand - v):
                            answer += 'R'
                            r_hand = v
                        elif abs(tmp - v) == abs(r_hand - v):
                            answer += 'R'
                            l_hand = v
                        else:
                            answer += 'L'
                            l_hand = v
                    else:
                        tmp = r_hand - 2
                        if abs(tmp - v) > abs(l_hand - v):
                            answer += 'L'
                            l_hand = v
                        elif abs(tmp - v) == abs(l_hand - v):
                            answer += 'L'
                            l_hand = v
                        else:
                            answer += 'R'
                            r_hand = v  
    return answer

아니 이거 원래 이렇게 안길었는데...... 계속 틀려서 추가하다가 모든 조건까지 추가하게되는 어리석은 코드입니다...'

2. 발상의 전환 code

def solution(numbers, hand):
    answer = ''
    l_hand = 10
    r_hand = 12
    for i, v  in enumerate(numbers):
        tmp = 0
        if v in [1, 4, 7]:
            answer += 'L'
            l_hand = v
        elif v in [3, 6, 9]:
            answer += 'R'
            r_hand = v
        else:
            v = 11 if v == 0 else v
            l_sum = sum(divmod(abs(l_hand-v), 3))
            r_sum = sum(divmod(abs(r_hand-v), 3))
            if l_sum == r_sum:
                if hand == 'right':
                    answer += 'R'
                    r_hand = v
                else:
                    answer += 'L'
                    l_hand = v
            elif l_sum > r_sum:
                answer += 'R'
                r_hand = v
            else:
                answer += 'L'
                l_hand = v    
    return answer  

3. 친구가 푼 java code

import java.util.Scanner;

class Solution {
	public String solution(int[] numbers, String hand) {
		String answer = "";

		int key[][] = {{1, 2, 3},	// 왼손 영역. 
						{4, 5, 6,},	// 중간 영역.
						{7, 8, 9},
						{42, 0 ,35}};	// 오른손 영역. 
		int LH[] = {3, 0};
		int RH[] = {3, 2};
		int input[] = new int[2];
		
	
		
		for(int p=0; p<numbers.length; p++) {
			for(int i=0; i<4; i++) {
				for(int j=0; j<3; j++) {
					if(key[i][j] == numbers[p]) {
						input[0] = i;
						input[1] = j;
						if(j==0) {
							LH[0] = i;
							LH[1] = j;
							answer += "L";
						}
						else if(j==2) {
							RH[0] = i;
							RH[1] = j;
							answer += "R";
						}
						else if(j==1) {
							int L = Math.abs((LH[0] - input[0])) + Math.abs((LH[1] - input[1]));
							int R = Math.abs((RH[0] - input[0])) + Math.abs((RH[1] - input[1]));
							
							if(L>R) {
								answer += "R";
								RH[0] = i;
								RH[1] = j;
							}
							else if(L<R) {
								answer += "L";
								LH[0] = i;
								LH[1] = j;
							}
							else if(L==R) {
								answer += hand.toUpperCase().toCharArray()[0];
								if(hand.toUpperCase().equals("RIGHT")) {
									RH[0] = i;
									RH[1] = j;
								}
								else if(hand.toUpperCase().equals("LEFT")) {
									LH[0] = i;
									LH[1] = j;
								}
							}
							
						}
					}
				}
			}
		}
		return answer;
	}
}

4. Feedback 📚

1. divmid(x, y)

- 두 숫자를 인자로 전달 받아 첫번째 인자를 두번째 인자로 나눈 몫과 나머지를 tuple 형식으로 반환한다.

# 모든 인자가 양수일 때
>>> divmod(4,2) 
(2, 0) 
>>> divmod(8,3) 
(2, 2)


# 인자중 음수값이 존재할 때
>>> divmod(10,-3) 
(-4, -2) 
>>> divmod(-10,-3) 
(3, -1) 
>>> divmod(-10,3) 
(-4, 2)

# 인자중 실수값이 존재할 때
>>> divmod(1.8,2) 
(0.0, 1.8) 
>>> divmod(1.8,0.4) 
(4.0, 0.19999999999999996) 
>>> divmod(5,0.4) 
(12.0, 0.19999999999999973)

처음에 코드 작성하기전에 생각했을때는 입력받은 숫자가 1, 4, 7 / 3, 6, 9를 제외한 숫자가 입력될 때 왼손과 오른손 눌린 숫자가 일직선인지 아닌지로 하면 금방 풀 줄 알았는데 예상외로 변수가 되게 많아서 헤맸었다. 처음부터 논리적으로 어떻게하면 효율적으로 풀지 더 고민하고 문제를 해결했으면 이렇게 시간이 오래 걸리지는 않았을텐데 암튼 앞으로 문제 풀때는 효율적으로 클린 코드가 될 수 있도록 노력좀 해야겠다..!!😐

profile
삽질의 기록들🐥

0개의 댓글