Programmers Algorithm - 키패드 누르기

Myung Jin Kim·2023년 10월 7일
1

주어진 조건에 따라 키패드를 왼손으로 누를건지 오른손으로 누를건지 Return 하는 문제다.

조건 중 2, 5, 8, 0 인 경우에 각 손 사이의 거리를 통해서 뭐로 누를 것인지만 잘 정해주면 기본적인 로직은 쉽게 나오는데

좀 더 알아봐야 하는 부분이 있다..

처음 코드는 다음과 같다.

const X_POSITION = 0;
const Y_POSITION = 1;
const DIRECTION = {
    LEFT : 'left',
    RIGHT : 'right',
    RESULT_LEFT : 'L',
    RESULT_RIGHT : 'R',
}


const keyPadPosition = {
    1 : [0, 0],
    2 : [0, 1],
    3 : [0, 2],
    4 : [1, 0],
    5 : [1, 1],
    6 : [1, 2],
    7 : [2, 0],
    8 : [2, 1],
    9 : [2, 2],
    "*" : [3, 0],
    0 : [3, 1],
    "#" : [3, 2],
}

const leftKeyPads = [1, 4, 7];
const rightKeyPads = [3, 6, 9];

const directionMapper = {
    [DIRECTION.LEFT] : DIRECTION.RESULT_LEFT,
    [DIRECTION.RIGHT] : DIRECTION.RESULT_RIGHT,
}

const getDistance = (handPos, numberPos) => {
    const xDistance = Math.abs(numberPos[X_POSITION] - handPos[X_POSITION]) ** 2;
    const yDistance = Math.abs(numberPos[Y_POSITION] - handPos[Y_POSITION]) ** 2;
    return Math.sqrt(xDistance + yDistance);
}


const getDirection = (number, hand, handPosition, numberPosition) => {
    
    if(leftKeyPads.includes(number)) {
        return DIRECTION.LEFT;
    }
    
    if(rightKeyPads.includes(number)) {
        return DIRECTION.RIGHT;
    }
    
    const leftDiff = getDistance(handPosition[DIRECTION.LEFT], numberPosition);
    const rightDiff =  getDistance(handPosition[DIRECTION.RIGHT], numberPosition);
    
    if(leftDiff === rightDiff) {
        return hand;
    }
    
    if(leftDiff > rightDiff) {
        return DIRECTION.RIGHT;
    }
    
    if(leftDiff < rightDiff) {
        return DIRECTION.LEFT;
    }
}
    
function solution(numbers, hand) {
    const handPosition = {
        [DIRECTION.LEFT] : keyPadPosition["*"],
        [DIRECTION.RIGHT] : keyPadPosition["#"],
    }

    return numbers.map(number => {
       const numberPosition = keyPadPosition[number];
       const direction = getDirection(number, hand, handPosition, numberPosition);
       handPosition[direction] = numberPosition;
       return directionMapper[direction];
    }).join('');
}

의심 1 : 정밀도

해당 로직으로 테스트케이스는 통과를 했지만 제출 시, 실패하는 케이스들이 생겼었다. 문제와 조건을 다시 읽고 보아도 별문제는 없어보였는데 Math.sqrt() 결과가 Floating Number 여서 혹시 정밀도 차이가 생겼나? 라는 생각이 들었다.

어차피 정확한 거리를 구하는게 아니다보니 X 와 Y 좌표 간의 거리를 구하고 더하는 것만으로 그 차이를 구별하게끔 했더니 문제는 통과를 할 수 있었다.

const getDistance = (handPos, numberPos) => {
    const xDistance = Math.abs(numberPos[X_POSITION] - handPos[X_POSITION]);
    const yDistance = Math.abs(numberPos[Y_POSITION] - handPos[Y_POSITION]);
    return xDistance + yDistance;
}

파생되는 문제 1.1 : 사실 정밀도가 문제가 아니다

우연히 발견한건데

const getDistance = (handPos, numberPos) => {
    const xDistance = Math.abs(numberPos[X_POSITION] - handPos[X_POSITION]);
    const yDistance = Math.abs(numberPos[Y_POSITION] - handPos[Y_POSITION]);
    return Math.sqrt(xDistance + yDistance);
}

** operator 를 빼고 제출을 해봤을 때도 문제를 통과했다.. Math.sqrt() 로 인해 Floating Number 가 리턴되는거기 때문에 정밀도 문제는 아닌 거로 판단은 되었지만 ** operator 가 적용이 안되는거라고 의심하기에는 Math.pow() 로 계산을 했을 때도 실패를 했다.

왜 실패를 했는지는 문제를 의심해봐야 하는건지 아직은 잘 모르겠어서 조금 찝찝한데 일단 문의라도 남겨봐야겠다.

profile
개발을 취미로 하고 싶은 개발자를 목표로 살고 있습니다

0개의 댓글