프론트엔드✏️/코드캠프

알고리즘 - [카카오 인턴] 키패드 누르기

당근먹는하니 2022. 6. 30. 19:32
728x90
반응형

 

이 전화 키패드에서 왼손과 오른손의 엄지손가락만을 이용해서 숫자만을 입력하려고 합니다.
맨 처음 왼손 엄지손가락은 * 키패드에 오른손 엄지손가락은 # 키패드 위치에서 시작하며, 엄지손가락을 사용하는 규칙은 다음과 같습니다.

  1. 엄지손가락은 상하좌우 4가지 방향으로만 이동할 수 있으며 키패드 이동 한 칸은 거리로 1에 해당합니다.
  2. 왼쪽 열의 3개의 숫자 1, 4, 7을 입력할 때는 왼손 엄지손가락을 사용합니다.
  3. 오른쪽 열의 3개의 숫자 3, 6, 9를 입력할 때는 오른손 엄지손가락을 사용합니다.
  4. 가운데 열의 4개의 숫자 2, 5, 8, 0을 입력할 때는 두 엄지손가락의 현재 키패드의 위치에서 더 가까운 엄지손가락을 사용합니다.
    4-1. 만약 두 엄지손가락의 거리가 같다면, 오른손잡이는 오른손 엄지손가락, 왼손잡이는 왼손 엄지손가락을 사용합니다.

순서대로 누를 번호가 담긴 배열 numbers, 왼손잡이인지 오른손잡이인 지를 나타내는 문자열 hand가 매개변수로 주어질 때, 각 번호를 누른 엄지손가락이 왼손인 지 오른손인 지를 나타내는 연속된 문자열 형태로 return 하도록 solution 함수를 완성해주세요.

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

 

코딩테스트 연습 - 키패드 누르기

[1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5] "right" "LRLLLRLLRRL" [7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2] "left" "LRLLRRLLLRR" [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] "right" "LLRLLRLLRL"

programmers.co.kr

 

 

푸는 걸 시도한 흔적

function solution(numbers, hand) {
  	let pad = [[1,2,3],[4,5,6],[7,8,9],['x',0,'x']];
	console.log(pad);
  if(hand === 'right') hand = 'R'; 
  else hand = "L";
  
    var answer = '';
  	let left = [3,0];
  	let right = [3,2];
  for(let i = 0; i<numbers.length; ++i) {
   
       if(numbers[i]===1||numbers[i]===4||numbers[i]===7) {
      answer += 'L';
      left = [(numbers[i]-1)/3,0]; // 2차원 배열로 봤을 때 인덱스 저장
    } else if(numbers[i]===3||numbers[i]===6||numbers[i]===9){
      answer += 'R';
      right = [(numbers[i]-3)/3,2];
      // 오른손이 3을 찍었으면 right는 [0,2]가 찍혀야해
      // 6을 찍었으면 right는 [1,2] , 9를 찍으면 [2,2]
    } else { // 2,5,8,0 
      console.log("2,5,8,0",numbers[i])
      // 이전 손들의 위치, 지금 찍어야할 숫자
     if(numbers[i]===0) {
       if(Math.abs(Math.abs(left[0]-3+Math.abs(left[1]-1), Math.abs(right[0]-3)+Math.abs(right[1]-1)))>0) {
        answer += 'L';
        right = [(numbers[i]-2)/3,1];
      } else if(Math.abs(Math.abs(left[0]-3)+Math.abs(left[1]-1), Math.abs(right[0]-3+Math.abs(right[1]-1)))<0) {
        answer += 'R';
        left = [(numbers[i]-2)/3,1];
      } else {
        answer += hand;
      }
     }
      console.log(left, right, numbers[i]);
      console.log([(numbers[i]-2)/3,1]) // 이걸 이차원 배열로 나타내면? 
      console.log(Math.abs(left[0]-(numbers[i]-2)/3)+Math.abs(left[1]-1), Math.abs(right[0]-(numbers[i]-2)/3+Math.abs(right[1]-1))) // 빼기 했을 때 0보다 크면 오른쪽이 누른다.

      if(Math.abs(Math.abs(left[0]-(numbers[i]-2)/3)+Math.abs(left[1]-1), Math.abs(right[0]-(numbers[i]-2)/3+Math.abs(right[1]-1)))>0) {
        answer += 'L';
        right = [(numbers[i]-2)/3,1];
      } else if(Math.abs(Math.abs(left[0]-(numbers[i]-2)/3)+Math.abs(left[1]-1), Math.abs(right[0]-(numbers[i]-2)/3+Math.abs(right[1]-1)))<0) {
        answer += 'R';
        left = [(numbers[i]-2)/3,1];
      } else {
        answer += hand;
      }
    }
  
    }
   
  console.log(answer, "이게?")
    return answer;
}

solution([1, 0, 3, 4, 5, 6, 7, 8, 9, 0], "right");


let sum = 1+'1';
console.log(sum);

 

마지막 문제.. 40일 도전의 마지막 ~~~ 

 

 

왼쪽으로 세 칸 이동한 것은 위로 한 칸 이동한 것과 같다 ,, 헉 충 격 . . . .

 

3으로 나누고 한 칸 남으면 그 나머지 값으로 왼쪽이나 오른쪽으로 이동해야겠지. 

 

 

// 멘토님 풀이
const leftNumbers = [1, 4, 7]; // 왼쪽 키패드에 해당하는 숫자들을 배치
const rightNumbers = [3, 6, 9];
function solution(numbers, hand) {
 let answer = "";
  // 두 엄지손가락이 어떤 위치에 있는지를 저장
  // 1번에서 얼마나 떨어져있는지를 볼 것임
  const current = {
    left : 10, // 9칸 + 자기 자신1
    right : 12,
  }
  for(let i = 0; i < numbers.length; ++i) {
    console.log(numbers[i]);
    if(leftNumbers.includes(numbers[i])) {
      // 누를 번호가 왼쪽 키패드에 해당된다면 (= 왼손 엄지손가락으로 누른다.)
      answer += "L";
      current["left"] = numbers[i];
    } else if(rightNumbers.includes(numbers[i])) {
      answer += "R";
      current["right"]= numbers[i];
    } else {
      // 가운데 키패드
      const locationObj = {...current}; // 왼손과 오른손의 위치 저장
      // 객체를 반복할거야
      for(let hand in locationObj) {
        numbers[i] = numbers[i] === 0 ? 11 : numbers[i]
        let location = Math.abs(numbers[i]-locationObj[hand])
        // 가운데 키패드로부터 얼마나 떨어져있는지 구한다. 
        console.log(hand, locationObj[hand]) // hand라는 이름으로 key를 가져옴 왼쪽과 오른쪽의 위치를 차례대로 가져와본다. 
        // 거리 차이가 3칸 이상일 때는 위 아래로 이동할 수 있다!!!
        if(location>=3) {
          location = Math.trunc(location / 3) + location%3; // 소수점 제거
        }
        locationObj[hand] = location;
      }
      if(locationObj["left"]===locationObj["right"]) {
        answer += hand === "left" ? "L" : "R";
        current[hand] = numbers[i];
        // console.log(numbers[i], locationObj, hand)
      } else {
        // 오른손 엄지손가락이 더 가까운 경우
        if(locationObj["left"]>locationObj["right"]) {
          answer += "R";
          current["right"] = numbers[i];
        } else { // 왼손 엄지가 더 가까운 경우
          answer += "L";
          current["left"] = numbers[i];
        }
      }
    }
  }
  return answer;
}

solution([1, 0, 3, 4, 5, 6, 7, 8, 9, 0], "right");

 

 키 : arr[0][0], arr[1][0]

 밸류 : arr[1][0], arr[1][1] 

 

entries

 

 

values, keys (밸류만/키만 뽑는다) 

 

// 멘토님 풀이 메서드
// const leftNumbers = [1, 4, 7]; // 왼쪽 키패드에 해당하는 숫자들을 배치
// const rightNumbers = [3, 6, 9];
const [leftNumbers, rightNumbers] = [[1,4,7],[3,6,9]]; // 비구조화 할당
function solution(numbers, hand) {
  const current = {
    left : 10, // 9칸 + 자기 자신1
    right : 12,
  }
  return numbers.reduce((acc, cur)=> {
    // 어떤 손가락으로 눌렀는지에 대한 최종 결과값("L","R")
    // 어떤 손으로 눌렀는지에 대한 결과값("left", "right")
    let [useFinger, target] = [ "", "" ];
    if(leftNumbers.includes(cur)) {
      [useFinger,target] = ["L", "left"];
    } else if(rightNumbers.includes(cur)) {
      [useFinger,target] ["R", "right"];
    } else {
      const locationObj = Object.entries(current).reduce((acc2,cur2)=> {
        cur = cur === 0 ? 11 : cur; 
        console.log(acc2,cur2, cur); // cur은 눌러야 할 번호
        let location = Math.abs(cur - cur2[1]);
        // console.log(acc2, cur2, cur, location);
        if(location >= 3) {
          location = Math.trunc(location / 3) + location%3;  
        }
        acc2[cur2[0]] = location;
        return acc2;
      },{})
      console.log(locationObj,cur); // cur를 눌러야할 때의 왼쪽손과 오른쪽 손이 있는 곳과 타겟이 몇 칸 차이나는지
      if(locationObj["left"]===locationObj["right"]) {
        [useFinger, target] = [ hand === "left" ? "L" : "R", hand]
      }
      console.log(locationObj);
    } else if(locationObj["left"]>locationObj["right"]) {
      [useFinger, target] = ["R", "right"]
    } else {
      [useFinger, target] = ["L","left"];
    }
    
    current[target] = cur; 
    return acc + useFinger; 
  },"")
}

solution([1, 0, 3, 4, 5, 6, 7, 8, 9, 0], "right");

 

 멘토님이 접근법은 괜찮은 것 같은데 중복된 코드가 일단 너무 많아서 정리해보면 좋을 것 같다고 하셨다.

그리고 객체로 접근하는게 더 쉬울 수도 있다고..!!

 

여기서 객체로 접근한 이유는 왼손이랑 오른손 위치 둘 다 해결하기 위해서고,

첫번째 풀이방법에서 current는 현재 손의 위치고 그걸 복사해서 얼마나 떨어져있는지 구하는 것 

728x90
반응형