[programmers]-キーボードを押す


1. Problem 📃


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



次の問題は、キーボードがある場合は、まず問題の条件に従って入力した指をロックし、それを返します.

2. Logic 👨‍🏫

  • 題の条件に示すように、1、4、7を入力すると、左手で値を入力して保存します.
  • 題の条件に示すように、3、6、9を入力すると右手で値を入力して保存します.
  • を除いて、2、5、8、0が現れた場合、鍵はLとRを求めることであり、この部分は上、下(-3、+3)、左、右(-1、+1)の変化を決定することができる.
  • の最後の手の位置と2、5、8、0の間の割引を求め、3で割ったシェアと残りの部分を加えるとキーボード上の距離を求めることができます.
  • 3. Code 💻


    1.失敗コード、、、考え方が間違っている😥

    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.考え方の変換コード

    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コード

    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)


    -2つの数値をパラメータとして渡し、tuple形式で1番目のパラメータを2番目のパラメータのシェアと残りの部分で割った値を返します.
    # 모든 인자가 양수일 때
    >>> 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以外の数字入力の場合、左手と右手で押された数字が一直線ではないかと思っていたのですが、意外にも変数が多くてうろうろしていました.最初から論理的にどうすれば効率的に問題を解くことができるかを考えていれば、問題を解決するのにそんなに時間がかからないので、とにかくこれから問題を解くときは効率的な整理コードになるように努力しなければなりません...!😐