[ココ]キーボードを押す(プログラマー)


問題の説明

  • 左手と右手の親指だけで
  • と入力.
  • 最初の左手親指は(*)、右手親指は(#)からの
  • ルール
    1)親指は上下左右4方向に移動でき、移動するセルは距離1に対応
    2)左の1、4、7列目に左手親指を使う
    3)右側の3、6、9列目に右手親指を使う
    4)中間の2、5、8、0列目を入力する場合は、現在の2つの親指の位置に近い親指を使用します.
    4-1)両親指の距離が等しい場合、右手の親指は右手、左手の親指は左手の親指は
  • を用いる.
  • のシリアル番号で、左利きか右利きかを示します.
    各番号の親指が左手か右手かを示す連続文字列を返します.
  • せいげんじょうけん

  • numbers配列の大きさは1000を超えず、
  • である.
  • numbers配列要素の値は0または9以下の整数
  • である.
  • 手は「左」または「右」
  • 左手親指は「L」、右手親指は「R」
  • に答える

    function solution(numbers, hand) {
        // 2차원 배열의 키패드
        const keypad = [
            [1,2,3],
            [4,5,6],
            [7,8,9],
            ['*',0,'#']
        ];
        // 누른 번호를 2차원 배열 keypad에서 찾고
        // x값 PosX[0], y값 PosY[0]를 담은 2차원배열 Position 
        const position = numbers.map(num=>{
            const posY = keypad.map((arr,idx)=>{
                if(arr.includes(num))
                    return 4-idx;
                return -1;
            }).filter(num=>num !== -1);
            const posX = keypad
            .filter(arr=>arr.includes(num))
            .map(dialogArr=>
                 dialogArr.map((dialog,idx)=>{
                    if(dialog === num)
                        return idx + 1;
                    return -1;
            }).filter(num => num !== -1))[0];
            
            return [posX[0],posY[0]];
        })
        
        const answer = [];
        // 누른 번호들의 좌표가 담긴 배열 position을 돌며 왼손,오른손 엄지손가락의 거리 계산
        // 현재 엄지손가락의 위치 currentPosition, 엄지손가락의 움직일 위치 movePosition
        position.reduce(
            (currentPosition, movePosition)=>{
                // 누를 번호로부터 왼손,오른손 엄지손가락으로부터 거리 leftDis, rightDis
                const leftDis = 
                      Math.abs(currentPosition[0][0] - movePosition[0])+
                      Math.abs(currentPosition[0][1] - movePosition[1]);
                const rightDis =
                      Math.abs(currentPosition[1][0] - movePosition[0])+
                      Math.abs(currentPosition[1][1] - movePosition[1]);
                // 이동하는 x좌표값이 1이면 왼쪽열 1,4,7이므로 'L'
                // 이동하는 x좌표값이 3이면 오른쪽열 3,6,9이므로 'R'
                if(movePosition[0] === 1){
                    answer.push('L');
                    return [movePosition, currentPosition[1]];
                }else if(movePosition[0] === 3){
                    answer.push('R');
                    return [currentPosition[0], movePosition];
                }
                // 누르는 번호가 가운데열 2,5,8,0일 경우
                // 거리를 비교해 'L' 또는 'R' 추가
                // 만약 거리가 같다면 오른손잡이인지 왼손잡이인지 확인
              	else{
                    if(leftDis < rightDis) answer.push('L');
                    if(leftDis > rightDis) answer.push('R');
                    if(leftDis === rightDis){
                        if(hand === 'right') answer.push('R');
                        else answer.push('L');
                    }
                    // 오른손잡이일때와 왼손잡이일때 비교
                    // 오른손잡이일때 거리가 같거나 가까우면 오른손 엄지손가락 이동
                    // 왼손잡이일때 거리가 같거나 가까우면 왼손 엄지손가락 이동
                    // 아닐 경우 반대로 결과 반환
                    if(hand === 'right'){
                        return leftDis < rightDis
                        ? [movePosition, currentPosition[1]]
                        : [currentPosition[0], movePosition];
                    }
                    return leftDis <= rightDis
                    ? [movePosition, currentPosition[1]]
                    : [currentPosition[0], movePosition];
                }
            },
            [[1,1],[3,1]]
        );
        return answer.join('');
    }

    チェックポイント

  • の2次元配列とmap法により各番号の座標値
  • を求める.
  • reduceメソッド
    1)左手、右手親指の初期位置を設定する
    2)現在の親指の位置と移動位置を比較し、
  • を更新する.