seongkyu.log
📖
알고리즘

[JS] 알고리즘 - 키패드 누르기

2023.01.04

[JS] 알고리즘 - 키패드 누르기

2020 카카오 인턴십에 나왔던 문제, 프로그래머스 기준 레벨 1이라는데 나 왜 눈물이..😥


구현 전 생각한 부분

  • 2차원 배열로 구현하지 않고, 1차원 배열로 구현 방향을 잡았어서, ** *,0,# ** 은 10, 11, 12로 처리했음
  • 3,6,9는 무조건 오른손, 1,4,7은 무조건 왼손으로 터치하며, 2,5,8,0은 두 엄지손가락에서 거리가 가까운 손가락이 터치한다.

1차 구현 결과

function solution(numbers, hand) {
  let result = [];
  let left = 0;
  let right = 0;

  numbers.map(function (item, index, array) {
    if (item === 1 || item === 4 || item === 7 || item === '*') {
      result.push('L');
      left = numbers[index];
    }
    if (item === 3 || item === 6 || item === 9 || item === '#') {
      result.push('R');
      right = numbers[index];
    }
    if (item === 2 || item === 5 || item === 8 || item === 0) {
      let compareLeft = Math.abs(numbers[index] - left);
      let compareRight = Math.abs(numbers[index] - right);

      if (compareLeft % 3 === 0) {
        compareLeft = compareLeft / 3;
      }
      if (compareRight % 3 === 0) {
        compareRight = compareRight / 3;
      }
      if (compareLeft < compareRight) {
        result.push('L');
        left = numbers[index];
      } else if (compareLeft > compareRight) {
        result.push('R');
        right = numbers[index];
      } else {
        if (hand === 'left') {
          result.push('L');
          left = numbers[index];
        }
        if (hand === 'right') {
          result.push('R');
          right = numbers[index];
        }
      }
    }
  });
  return result.join('');
}
  • 테스트 케이스 1만 통과가 되었다.(테케1 기준으로 코드 작성 하긴함)
  • 구현 전 생각했던 것 처럼 1,4,7은 왼손 3,6,9는 오른손으로 푸쉬시켰으며, 2,5,8,0일때 거리의 절대값이 작은 쪽이 더 가깝다고 체크했다.
    • 또한, 3의 배수는 바로 위/아래에 있다고 판단하였음(ex : 키패드 ‘5’와 ‘8’). 따라서 3으로 나누어 절대값을 가공했다.
  • left, right에 저장된 값들은 다시 left, right에 재할당했다.
  • 테스트 케이스2, 3을 해결하기 위해서 다음과 같이 구현했다.

2차 구현 결과

function solution(numbers, hand) {
  let result = [];
  let left = -1; // 아직 값이 안들어있음
  let right = -1; // 아직 값이 안들어있음  그래서 이값들을 -1으로 참조하면 값 출력이 제대로 안됨. left -1은 *, right -1은 #

  function rightLogic(numbers, index) {
    result.push('R');
    right = numbers[index];
  }

  function leftLogic(numbers, index) {
    result.push('L');
    left = numbers[index];
  }

  numbers.map(function (item, index, array) {
    if (item === 1 || item === 4 || item === 7 || item === '*') {
      leftLogic(numbers, index);
    }
    if (item === 3 || item === 6 || item === 9 || item === '#') {
      rightLogic(numbers, index);
    }
    if (item === 2 || item === 5 || item === 8 || item === 0) {
      if (item === 0) {
        numbers[index] = 11;
      }
      if (left === -1) {
        left = 10;
      }
      if (right === -1) {
        right = 12;
      }
      let LeftDistance = Math.abs(numbers[index] - left);
      let RightDistance = Math.abs(numbers[index] - right);

      let compareLeftRightDistance = Math.abs(LeftDistance - RightDistance);
      if (LeftDistance % 3 === 0) {
        LeftDistance = LeftDistance / 3;
      }
      if (RightDistance % 3 === 0) {
        RightDistance = RightDistance / 3;
      }
      if (compareLeftRightDistance !== 2) {
        if (LeftDistance < RightDistance) {
          leftLogic(numbers, index);
        } else if (LeftDistance > RightDistance) {
          rightLogic(numbers, index);
        } else {
          if (hand === 'left') {
            leftLogic(numbers, index);
          }
          if (hand === 'right') {
            rightLogic(numbers, index);
          }
        }
      }

      if (compareLeftRightDistance === 2) {
        if (numbers[index] - 1 === left && numbers[index] + 1 === right) {
          if (hand === 'left') {
            leftLogic(numbers, index);
          }
          if (hand === 'right') {
            rightLogic(numbers, index);
          }
        }
        if (numbers[index] - 1 === left) {
          leftLogic(numbers, index);
        }
        if (numbers[index] + 1 === right) {
          rightLogic(numbers, index);
        }

        if (numbers[index] > left) {
          leftLogic(numbers, index);
        }
        if (numbers[index] < left) {
          rightLogic(numbers, index);
        }
      }
    }
  });
  return result.join('');
}
  • 테스트 케이스 2,3에서는 통과가 되는데 1에서만 안되는 현상 발생🥲
  • left, right를 -1로 초기화했다(숫자 범위 내에 없는 값으로 골랐음)

3차 구현 결과

  • 테스트케이스 1,2,3은 통과되었는데, 채점에서는 45점을 넘기지 못함 :(

/**
 *
 * 못 풀 었 다 ㅠ_ㅠ
 */

function solution(numbers, hand) {
  let result = [];
  let left = -1;
  let right = -1;

  function rightLogic(numbers, index) {
    result.push('R');
    right = numbers[index];
  }
  function leftLogic(numbers, index) {
    result.push('L');
    left = numbers[index];
  }

  function selectHand(numbers, index, hand) {
    if (hand === 'left') {
      leftLogic(numbers, index);
    }
    if (hand === 'right') {
      rightLogic(numbers, index);
    }
  }

  numbers.map(function (item, index, array) {
    if (item === 1 || item === 4 || item === 7 || item === '*') {
      leftLogic(numbers, index);
    }
    if (item === 3 || item === 6 || item === 9 || item === '#') {
      rightLogic(numbers, index);
    }
    if (item === 2 || item === 5 || item === 8 || item === 0) {
      if (item === 0) numbers[index] = 11;
      if (left === -1) left = 10;
      if (right === -1) right = 12;
      let LeftDistance = Math.abs(numbers[index] - left);
      let rightDistance = Math.abs(numbers[index] - right);
      if (LeftDistance % 3 === 0) {
        LeftDistance = LeftDistance / 3;
      }
      if (rightDistance % 3 === 0) {
        rightDistance = rightDistance / 3;
      }

      if (right + 2 == numbers[index] && right - 2 == left) {
        selectHand(numbers, index, hand);
      } else if (left + 2 == right && left - 2 == numbers[index]) {
        selectHand(numbers, index, hand);
      } else if (left + 3 === numbers[index] || left - 3 === numbers[index]) {
        leftLogic(numbers, index);
      } else if (right + 3 === numbers[index] || left - 3 === numbers[index]) {
        rightLogic(numbers, index);
      } else if (LeftDistance < rightDistance) {
        leftLogic(numbers, index);
      } else if (LeftDistance > rightDistance) {
        rightLogic(numbers, index);
      } else {
        selectHand(numbers, index, hand);
      }
    }
  });
  return result.join('');
}
  • 테스트케이스에 맞춰서 조건을 설정해주면 통과가 될 줄 알았는데 채점을 돌렸을 때 통과되지 않는 케이스 발생
  • right에서 2를 더한 값이 numbers[index]이고 2를 뺀 값이 left값이라면 (ex : index : 5, left : 1 , right : 3 hand를 고르는 함수로 넘어가도록했다.

마무리

  • 일차원 배열로 해결하려다 보니, *, 0, #을 후처리해야 하는 과정이 필요했다. 차라리 JSON 형식으로 만들었으면 후처리하는 과정은 필요없었을 것 같다.
    • 이로 인해 if 조건을 무분별하게 사용한 것 같다.
  • 다른사람들이 쓴 코드를 확인해보니 이차원 배열을 주로 사용했다. 애초에 나도 이차원으로 방향을 잡았어야 했는데, 처음 일차원으로 구현을 시작해서 테스트 케이스를 통과하다보니 뭔가 될 것 같은데?라는 생각으로 계속 밀고 나갔다.
  • 혹시, 1차원 배열로 해결하신 분이 이 글을 보신다면 문제점을 말씀해주시면 감사하겠습니다 ㅠㅠ
👇 도움이 되셨다면 👇

© Powered by danmin